diff --git a/agentrun/agent_runtime/api/control.py b/agentrun/agent_runtime/api/control.py index c3a3847..8b76d45 100644 --- a/agentrun/agent_runtime/api/control.py +++ b/agentrun/agent_runtime/api/control.py @@ -21,9 +21,6 @@ CreateAgentRuntimeEndpointRequest, CreateAgentRuntimeInput, CreateAgentRuntimeRequest, - DeleteAgentRuntimeEndpointRequest, - DeleteAgentRuntimeRequest, - GetAgentRuntimeEndpointRequest, GetAgentRuntimeRequest, ListAgentRuntimeEndpointsOutput, ListAgentRuntimeEndpointsRequest, @@ -196,7 +193,6 @@ def delete_agent_runtime( client = self._get_client(config) response = client.delete_agent_runtime_with_options( agent_id, - DeleteAgentRuntimeRequest(), headers=headers or {}, runtime=RuntimeOptions(), ) @@ -252,7 +248,6 @@ async def delete_agent_runtime_async( client = self._get_client(config) response = await client.delete_agent_runtime_with_options_async( agent_id, - DeleteAgentRuntimeRequest(), headers=headers or {}, runtime=RuntimeOptions(), ) @@ -783,7 +778,6 @@ def delete_agent_runtime_endpoint( response = client.delete_agent_runtime_endpoint_with_options( agent_id, endpoint_id, - DeleteAgentRuntimeEndpointRequest(), headers=headers or {}, runtime=RuntimeOptions(), ) @@ -844,7 +838,6 @@ async def delete_agent_runtime_endpoint_async( await client.delete_agent_runtime_endpoint_with_options_async( agent_id, endpoint_id, - DeleteAgentRuntimeEndpointRequest(), headers=headers or {}, runtime=RuntimeOptions(), ) @@ -1035,7 +1028,6 @@ def get_agent_runtime_endpoint( response = client.get_agent_runtime_endpoint_with_options( agent_id, endpoint_id, - GetAgentRuntimeEndpointRequest(), headers=headers or {}, runtime=RuntimeOptions(), ) @@ -1096,7 +1088,6 @@ async def get_agent_runtime_endpoint_async( await client.get_agent_runtime_endpoint_with_options_async( agent_id, endpoint_id, - GetAgentRuntimeEndpointRequest(), headers=headers or {}, runtime=RuntimeOptions(), ) diff --git a/pyproject.toml b/pyproject.toml index 8ea57d9..126f0df 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ dependencies = [ "litellm>=1.79.3", "alibabacloud-devs20230714>=2.4.1", "pydash>=8.0.5", - "alibabacloud-agentrun20250910>=5.6.1", + "alibabacloud-agentrun20250910>=5.6.3", "alibabacloud_tea_openapi>=0.4.2", "alibabacloud_bailian20231229>=2.6.2", "agentrun-mem0ai>=0.0.10", diff --git a/tests/unittests/agent_runtime/api/test_control.py b/tests/unittests/agent_runtime/api/test_control.py new file mode 100644 index 0000000..6f91335 --- /dev/null +++ b/tests/unittests/agent_runtime/api/test_control.py @@ -0,0 +1,201 @@ +""" +测试 AgentRuntimeControlAPI 对底层 SDK client 的调用是否与 SDK 方法签名匹配。 +""" + +from unittest.mock import create_autospec, MagicMock, patch + +from alibabacloud_agentrun20250910.client import Client as AgentRunClient +from alibabacloud_agentrun20250910.models import ( + CreateAgentRuntimeEndpointInput, + CreateAgentRuntimeInput, + GetAgentRuntimeRequest, + ListAgentRuntimeEndpointsRequest, + ListAgentRuntimesRequest, + ListAgentRuntimeVersionsRequest, + UpdateAgentRuntimeEndpointInput, + UpdateAgentRuntimeInput, +) +import pytest + +from agentrun.agent_runtime.api.control import AgentRuntimeControlAPI +from agentrun.utils.config import Config + + +@pytest.fixture +def mock_config(): + return Config( + access_key_id="test-ak", + access_key_secret="test-sk", + region_id="cn-hangzhou", + control_endpoint="https://agentrun.cn-hangzhou.aliyuncs.com", + ) + + +@pytest.fixture +def mock_response(): + response = MagicMock() + response.body.request_id = "test-request-id" + response.body.data = MagicMock() + return response + + +@pytest.fixture +def api_and_client(mock_config, mock_response): + api = AgentRuntimeControlAPI(config=mock_config) + mock_client = create_autospec(AgentRunClient, instance=True) + + for attr in dir(AgentRunClient): + if "with_options" in attr: + getattr(mock_client, attr).return_value = mock_response + + with patch.object(api, "_get_client", return_value=mock_client): + yield api, mock_client + + +class TestAgentRuntimeControlAPISignatures: + + def test_create_agent_runtime(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateAgentRuntimeInput) + api.create_agent_runtime(input_data) + client.create_agent_runtime_with_options.assert_called_once() + + def test_delete_agent_runtime(self, api_and_client): + api, client = api_and_client + api.delete_agent_runtime("agent-123") + client.delete_agent_runtime_with_options.assert_called_once() + + def test_update_agent_runtime(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateAgentRuntimeInput) + api.update_agent_runtime("agent-123", input_data) + client.update_agent_runtime_with_options.assert_called_once() + + def test_get_agent_runtime(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=GetAgentRuntimeRequest) + api.get_agent_runtime("agent-123", input_data) + client.get_agent_runtime_with_options.assert_called_once() + + def test_list_agent_runtimes(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListAgentRuntimesRequest) + api.list_agent_runtimes(input_data) + client.list_agent_runtimes_with_options.assert_called_once() + + def test_create_agent_runtime_endpoint(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateAgentRuntimeEndpointInput) + api.create_agent_runtime_endpoint("agent-123", input_data) + client.create_agent_runtime_endpoint_with_options.assert_called_once() + + def test_delete_agent_runtime_endpoint(self, api_and_client): + api, client = api_and_client + api.delete_agent_runtime_endpoint("agent-123", "endpoint-456") + client.delete_agent_runtime_endpoint_with_options.assert_called_once() + + def test_update_agent_runtime_endpoint(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateAgentRuntimeEndpointInput) + api.update_agent_runtime_endpoint( + "agent-123", "endpoint-456", input_data + ) + client.update_agent_runtime_endpoint_with_options.assert_called_once() + + def test_get_agent_runtime_endpoint(self, api_and_client): + api, client = api_and_client + api.get_agent_runtime_endpoint("agent-123", "endpoint-456") + client.get_agent_runtime_endpoint_with_options.assert_called_once() + + def test_list_agent_runtime_endpoints(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListAgentRuntimeEndpointsRequest) + api.list_agent_runtime_endpoints("agent-123", input_data) + client.list_agent_runtime_endpoints_with_options.assert_called_once() + + def test_list_agent_runtime_versions(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListAgentRuntimeVersionsRequest) + api.list_agent_runtime_versions("agent-123", input_data) + client.list_agent_runtime_versions_with_options.assert_called_once() + + +class TestAgentRuntimeControlAPIAsyncSignatures: + + @pytest.mark.asyncio + async def test_create_agent_runtime_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateAgentRuntimeInput) + await api.create_agent_runtime_async(input_data) + client.create_agent_runtime_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_delete_agent_runtime_async(self, api_and_client): + api, client = api_and_client + await api.delete_agent_runtime_async("agent-123") + client.delete_agent_runtime_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_update_agent_runtime_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateAgentRuntimeInput) + await api.update_agent_runtime_async("agent-123", input_data) + client.update_agent_runtime_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_get_agent_runtime_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=GetAgentRuntimeRequest) + await api.get_agent_runtime_async("agent-123", input_data) + client.get_agent_runtime_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_list_agent_runtimes_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListAgentRuntimesRequest) + await api.list_agent_runtimes_async(input_data) + client.list_agent_runtimes_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_create_agent_runtime_endpoint_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateAgentRuntimeEndpointInput) + await api.create_agent_runtime_endpoint_async("agent-123", input_data) + client.create_agent_runtime_endpoint_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_delete_agent_runtime_endpoint_async(self, api_and_client): + api, client = api_and_client + await api.delete_agent_runtime_endpoint_async( + "agent-123", "endpoint-456" + ) + client.delete_agent_runtime_endpoint_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_update_agent_runtime_endpoint_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateAgentRuntimeEndpointInput) + await api.update_agent_runtime_endpoint_async( + "agent-123", "endpoint-456", input_data + ) + client.update_agent_runtime_endpoint_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_get_agent_runtime_endpoint_async(self, api_and_client): + api, client = api_and_client + await api.get_agent_runtime_endpoint_async("agent-123", "endpoint-456") + client.get_agent_runtime_endpoint_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_list_agent_runtime_endpoints_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListAgentRuntimeEndpointsRequest) + await api.list_agent_runtime_endpoints_async("agent-123", input_data) + client.list_agent_runtime_endpoints_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_list_agent_runtime_versions_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListAgentRuntimeVersionsRequest) + await api.list_agent_runtime_versions_async("agent-123", input_data) + client.list_agent_runtime_versions_with_options_async.assert_called_once() diff --git a/tests/unittests/credential/api/__init__.py b/tests/unittests/credential/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unittests/credential/api/test_control.py b/tests/unittests/credential/api/test_control.py new file mode 100644 index 0000000..3b3df19 --- /dev/null +++ b/tests/unittests/credential/api/test_control.py @@ -0,0 +1,114 @@ +""" +测试 CredentialControlAPI 对底层 SDK client 的调用是否与 SDK 方法签名匹配。 +""" + +from unittest.mock import create_autospec, MagicMock, patch + +from alibabacloud_agentrun20250910.client import Client as AgentRunClient +from alibabacloud_agentrun20250910.models import ( + CreateCredentialInput, + ListCredentialsRequest, + UpdateCredentialInput, +) +import pytest + +from agentrun.credential.api.control import CredentialControlAPI +from agentrun.utils.config import Config + + +@pytest.fixture +def mock_config(): + return Config( + access_key_id="test-ak", + access_key_secret="test-sk", + region_id="cn-hangzhou", + control_endpoint="https://agentrun.cn-hangzhou.aliyuncs.com", + ) + + +@pytest.fixture +def mock_response(): + response = MagicMock() + response.body.request_id = "test-request-id" + response.body.data = MagicMock() + return response + + +@pytest.fixture +def api_and_client(mock_config, mock_response): + api = CredentialControlAPI(config=mock_config) + mock_client = create_autospec(AgentRunClient, instance=True) + + for attr in dir(AgentRunClient): + if "with_options" in attr: + getattr(mock_client, attr).return_value = mock_response + + with patch.object(api, "_get_client", return_value=mock_client): + yield api, mock_client + + +class TestCredentialControlAPISignatures: + + def test_create_credential(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateCredentialInput) + api.create_credential(input_data) + client.create_credential_with_options.assert_called_once() + + def test_delete_credential(self, api_and_client): + api, client = api_and_client + api.delete_credential("test-cred") + client.delete_credential_with_options.assert_called_once() + + def test_update_credential(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateCredentialInput) + api.update_credential("test-cred", input_data) + client.update_credential_with_options.assert_called_once() + + def test_get_credential(self, api_and_client): + api, client = api_and_client + api.get_credential("test-cred") + client.get_credential_with_options.assert_called_once() + + def test_list_credentials(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListCredentialsRequest) + api.list_credentials(input_data) + client.list_credentials_with_options.assert_called_once() + + +class TestCredentialControlAPIAsyncSignatures: + + @pytest.mark.asyncio + async def test_create_credential_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateCredentialInput) + await api.create_credential_async(input_data) + client.create_credential_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_delete_credential_async(self, api_and_client): + api, client = api_and_client + await api.delete_credential_async("test-cred") + client.delete_credential_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_update_credential_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateCredentialInput) + await api.update_credential_async("test-cred", input_data) + client.update_credential_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_get_credential_async(self, api_and_client): + api, client = api_and_client + await api.get_credential_async("test-cred") + client.get_credential_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_list_credentials_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListCredentialsRequest) + await api.list_credentials_async(input_data) + client.list_credentials_with_options_async.assert_called_once() diff --git a/tests/unittests/knowledgebase/api/test_control.py b/tests/unittests/knowledgebase/api/test_control.py new file mode 100644 index 0000000..d12f713 --- /dev/null +++ b/tests/unittests/knowledgebase/api/test_control.py @@ -0,0 +1,114 @@ +""" +测试 KnowledgeBaseControlAPI 对底层 SDK client 的调用是否与 SDK 方法签名匹配。 +""" + +from unittest.mock import create_autospec, MagicMock, patch + +from alibabacloud_agentrun20250910.client import Client as AgentRunClient +from alibabacloud_agentrun20250910.models import ( + CreateKnowledgeBaseInput, + ListKnowledgeBasesRequest, + UpdateKnowledgeBaseInput, +) +import pytest + +from agentrun.knowledgebase.api.control import KnowledgeBaseControlAPI +from agentrun.utils.config import Config + + +@pytest.fixture +def mock_config(): + return Config( + access_key_id="test-ak", + access_key_secret="test-sk", + region_id="cn-hangzhou", + control_endpoint="https://agentrun.cn-hangzhou.aliyuncs.com", + ) + + +@pytest.fixture +def mock_response(): + response = MagicMock() + response.body.request_id = "test-request-id" + response.body.data = MagicMock() + return response + + +@pytest.fixture +def api_and_client(mock_config, mock_response): + api = KnowledgeBaseControlAPI(config=mock_config) + mock_client = create_autospec(AgentRunClient, instance=True) + + for attr in dir(AgentRunClient): + if "with_options" in attr: + getattr(mock_client, attr).return_value = mock_response + + with patch.object(api, "_get_client", return_value=mock_client): + yield api, mock_client + + +class TestKnowledgeBaseControlAPISignatures: + + def test_create_knowledge_base(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateKnowledgeBaseInput) + api.create_knowledge_base(input_data) + client.create_knowledge_base_with_options.assert_called_once() + + def test_delete_knowledge_base(self, api_and_client): + api, client = api_and_client + api.delete_knowledge_base("test-kb") + client.delete_knowledge_base_with_options.assert_called_once() + + def test_update_knowledge_base(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateKnowledgeBaseInput) + api.update_knowledge_base("test-kb", input_data) + client.update_knowledge_base_with_options.assert_called_once() + + def test_get_knowledge_base(self, api_and_client): + api, client = api_and_client + api.get_knowledge_base("test-kb") + client.get_knowledge_base_with_options.assert_called_once() + + def test_list_knowledge_bases(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListKnowledgeBasesRequest) + api.list_knowledge_bases(input_data) + client.list_knowledge_bases_with_options.assert_called_once() + + +class TestKnowledgeBaseControlAPIAsyncSignatures: + + @pytest.mark.asyncio + async def test_create_knowledge_base_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateKnowledgeBaseInput) + await api.create_knowledge_base_async(input_data) + client.create_knowledge_base_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_delete_knowledge_base_async(self, api_and_client): + api, client = api_and_client + await api.delete_knowledge_base_async("test-kb") + client.delete_knowledge_base_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_update_knowledge_base_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateKnowledgeBaseInput) + await api.update_knowledge_base_async("test-kb", input_data) + client.update_knowledge_base_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_get_knowledge_base_async(self, api_and_client): + api, client = api_and_client + await api.get_knowledge_base_async("test-kb") + client.get_knowledge_base_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_list_knowledge_bases_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListKnowledgeBasesRequest) + await api.list_knowledge_bases_async(input_data) + client.list_knowledge_bases_with_options_async.assert_called_once() diff --git a/tests/unittests/memory_collection/api/__init__.py b/tests/unittests/memory_collection/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unittests/memory_collection/api/test_control.py b/tests/unittests/memory_collection/api/test_control.py new file mode 100644 index 0000000..da20f11 --- /dev/null +++ b/tests/unittests/memory_collection/api/test_control.py @@ -0,0 +1,114 @@ +""" +测试 MemoryCollectionControlAPI 对底层 SDK client 的调用是否与 SDK 方法签名匹配。 +""" + +from unittest.mock import create_autospec, MagicMock, patch + +from alibabacloud_agentrun20250910.client import Client as AgentRunClient +from alibabacloud_agentrun20250910.models import ( + CreateMemoryCollectionInput, + ListMemoryCollectionsRequest, + UpdateMemoryCollectionInput, +) +import pytest + +from agentrun.memory_collection.api.control import MemoryCollectionControlAPI +from agentrun.utils.config import Config + + +@pytest.fixture +def mock_config(): + return Config( + access_key_id="test-ak", + access_key_secret="test-sk", + region_id="cn-hangzhou", + control_endpoint="https://agentrun.cn-hangzhou.aliyuncs.com", + ) + + +@pytest.fixture +def mock_response(): + response = MagicMock() + response.body.request_id = "test-request-id" + response.body.data = MagicMock() + return response + + +@pytest.fixture +def api_and_client(mock_config, mock_response): + api = MemoryCollectionControlAPI(config=mock_config) + mock_client = create_autospec(AgentRunClient, instance=True) + + for attr in dir(AgentRunClient): + if "with_options" in attr: + getattr(mock_client, attr).return_value = mock_response + + with patch.object(api, "_get_client", return_value=mock_client): + yield api, mock_client + + +class TestMemoryCollectionControlAPISignatures: + + def test_create_memory_collection(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateMemoryCollectionInput) + api.create_memory_collection(input_data) + client.create_memory_collection_with_options.assert_called_once() + + def test_delete_memory_collection(self, api_and_client): + api, client = api_and_client + api.delete_memory_collection("test-collection") + client.delete_memory_collection_with_options.assert_called_once() + + def test_update_memory_collection(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateMemoryCollectionInput) + api.update_memory_collection("test-collection", input_data) + client.update_memory_collection_with_options.assert_called_once() + + def test_get_memory_collection(self, api_and_client): + api, client = api_and_client + api.get_memory_collection("test-collection") + client.get_memory_collection_with_options.assert_called_once() + + def test_list_memory_collections(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListMemoryCollectionsRequest) + api.list_memory_collections(input_data) + client.list_memory_collections_with_options.assert_called_once() + + +class TestMemoryCollectionControlAPIAsyncSignatures: + + @pytest.mark.asyncio + async def test_create_memory_collection_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateMemoryCollectionInput) + await api.create_memory_collection_async(input_data) + client.create_memory_collection_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_delete_memory_collection_async(self, api_and_client): + api, client = api_and_client + await api.delete_memory_collection_async("test-collection") + client.delete_memory_collection_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_update_memory_collection_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateMemoryCollectionInput) + await api.update_memory_collection_async("test-collection", input_data) + client.update_memory_collection_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_get_memory_collection_async(self, api_and_client): + api, client = api_and_client + await api.get_memory_collection_async("test-collection") + client.get_memory_collection_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_list_memory_collections_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListMemoryCollectionsRequest) + await api.list_memory_collections_async(input_data) + client.list_memory_collections_with_options_async.assert_called_once() diff --git a/tests/unittests/model/api/test_control.py b/tests/unittests/model/api/test_control.py new file mode 100644 index 0000000..2dd6423 --- /dev/null +++ b/tests/unittests/model/api/test_control.py @@ -0,0 +1,181 @@ +""" +测试 ModelControlAPI 对底层 SDK client 的调用是否与 SDK 方法签名匹配。 +""" + +from unittest.mock import create_autospec, MagicMock, patch + +from alibabacloud_agentrun20250910.client import Client as AgentRunClient +from alibabacloud_agentrun20250910.models import ( + CreateModelProxyInput, + CreateModelServiceInput, + ListModelProxiesRequest, + ListModelServicesRequest, + UpdateModelProxyInput, + UpdateModelServiceInput, +) +import pytest + +from agentrun.model.api.control import ModelControlAPI +from agentrun.utils.config import Config + + +@pytest.fixture +def mock_config(): + return Config( + access_key_id="test-ak", + access_key_secret="test-sk", + region_id="cn-hangzhou", + control_endpoint="https://agentrun.cn-hangzhou.aliyuncs.com", + ) + + +@pytest.fixture +def mock_response(): + response = MagicMock() + response.body.request_id = "test-request-id" + response.body.data = MagicMock() + return response + + +@pytest.fixture +def api_and_client(mock_config, mock_response): + api = ModelControlAPI(config=mock_config) + mock_client = create_autospec(AgentRunClient, instance=True) + + for attr in dir(AgentRunClient): + if "with_options" in attr: + getattr(mock_client, attr).return_value = mock_response + + with patch.object(api, "_get_client", return_value=mock_client): + yield api, mock_client + + +class TestModelServiceControlAPISignatures: + + def test_create_model_service(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateModelServiceInput) + api.create_model_service(input_data) + client.create_model_service_with_options.assert_called_once() + + def test_delete_model_service(self, api_and_client): + api, client = api_and_client + api.delete_model_service("test-service") + client.delete_model_service_with_options.assert_called_once() + + def test_update_model_service(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateModelServiceInput) + api.update_model_service("test-service", input_data) + client.update_model_service_with_options.assert_called_once() + + def test_get_model_service(self, api_and_client): + api, client = api_and_client + api.get_model_service("test-service") + client.get_model_service_with_options.assert_called_once() + + def test_list_model_services(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListModelServicesRequest) + api.list_model_services(input_data) + client.list_model_services_with_options.assert_called_once() + + +class TestModelProxyControlAPISignatures: + + def test_create_model_proxy(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateModelProxyInput) + api.create_model_proxy(input_data) + client.create_model_proxy_with_options.assert_called_once() + + def test_delete_model_proxy(self, api_and_client): + api, client = api_and_client + api.delete_model_proxy("test-proxy") + client.delete_model_proxy_with_options.assert_called_once() + + def test_update_model_proxy(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateModelProxyInput) + api.update_model_proxy("test-proxy", input_data) + client.update_model_proxy_with_options.assert_called_once() + + def test_get_model_proxy(self, api_and_client): + api, client = api_and_client + api.get_model_proxy("test-proxy") + client.get_model_proxy_with_options.assert_called_once() + + def test_list_model_proxies(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListModelProxiesRequest) + api.list_model_proxies(input_data) + client.list_model_proxies_with_options.assert_called_once() + + +class TestModelControlAPIAsyncSignatures: + + @pytest.mark.asyncio + async def test_create_model_service_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateModelServiceInput) + await api.create_model_service_async(input_data) + client.create_model_service_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_delete_model_service_async(self, api_and_client): + api, client = api_and_client + await api.delete_model_service_async("test-service") + client.delete_model_service_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_update_model_service_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateModelServiceInput) + await api.update_model_service_async("test-service", input_data) + client.update_model_service_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_get_model_service_async(self, api_and_client): + api, client = api_and_client + await api.get_model_service_async("test-service") + client.get_model_service_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_list_model_services_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListModelServicesRequest) + await api.list_model_services_async(input_data) + client.list_model_services_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_create_model_proxy_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateModelProxyInput) + await api.create_model_proxy_async(input_data) + client.create_model_proxy_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_delete_model_proxy_async(self, api_and_client): + api, client = api_and_client + await api.delete_model_proxy_async("test-proxy") + client.delete_model_proxy_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_update_model_proxy_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateModelProxyInput) + await api.update_model_proxy_async("test-proxy", input_data) + client.update_model_proxy_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_get_model_proxy_async(self, api_and_client): + api, client = api_and_client + await api.get_model_proxy_async("test-proxy") + client.get_model_proxy_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_list_model_proxies_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListModelProxiesRequest) + await api.list_model_proxies_async(input_data) + client.list_model_proxies_with_options_async.assert_called_once() diff --git a/tests/unittests/sandbox/api/test_control.py b/tests/unittests/sandbox/api/test_control.py new file mode 100644 index 0000000..7d1df7d --- /dev/null +++ b/tests/unittests/sandbox/api/test_control.py @@ -0,0 +1,172 @@ +""" +测试 SandboxControlAPI 对底层 SDK client 的调用是否与 SDK 方法签名匹配。 + +使用 create_autospec(AgentRunClient) 来 mock _get_client 的返回值, +autospec 会强制校验方法签名,确保 SDK 方法签名变更时能及时检测出来。 +""" + +from unittest.mock import create_autospec, MagicMock, patch + +from alibabacloud_agentrun20250910.client import Client as AgentRunClient +from alibabacloud_agentrun20250910.models import ( + CreateSandboxInput, + CreateTemplateInput, + ListSandboxesRequest, + ListTemplatesRequest, + UpdateTemplateInput, +) +import pytest + +from agentrun.sandbox.api.control import SandboxControlAPI +from agentrun.utils.config import Config + + +@pytest.fixture +def mock_config(): + return Config( + access_key_id="test-ak", + access_key_secret="test-sk", + region_id="cn-hangzhou", + control_endpoint="https://agentrun.cn-hangzhou.aliyuncs.com", + ) + + +@pytest.fixture +def mock_response(): + """构造通用的 SDK 响应对象""" + response = MagicMock() + response.body.request_id = "test-request-id" + response.body.data = MagicMock() + return response + + +@pytest.fixture +def api_and_client(mock_config, mock_response): + """返回 (api, mock_client),mock_client 使用 create_autospec 强制校验方法签名""" + api = SandboxControlAPI(config=mock_config) + mock_client = create_autospec(AgentRunClient, instance=True) + + # 为所有 _with_options 方法设置默认返回值 + for attr in dir(AgentRunClient): + if "with_options" in attr: + getattr(mock_client, attr).return_value = mock_response + + with patch.object(api, "_get_client", return_value=mock_client): + yield api, mock_client + + +class TestSandboxControlAPISignatures: + """测试 SandboxControlAPI 同步方法调用是否匹配 SDK 签名""" + + def test_create_template(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateTemplateInput) + api.create_template(input_data) + client.create_template_with_options.assert_called_once() + + def test_delete_template(self, api_and_client): + api, client = api_and_client + api.delete_template("test-template") + client.delete_template_with_options.assert_called_once() + + def test_update_template(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateTemplateInput) + api.update_template("test-template", input_data) + client.update_template_with_options.assert_called_once() + + def test_get_template(self, api_and_client): + api, client = api_and_client + api.get_template("test-template") + client.get_template_with_options.assert_called_once() + + def test_list_templates(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListTemplatesRequest) + api.list_templates(input_data) + client.list_templates_with_options.assert_called_once() + + def test_create_sandbox(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateSandboxInput) + api.create_sandbox(input_data) + client.create_sandbox_with_options.assert_called_once() + + def test_stop_sandbox(self, api_and_client): + api, client = api_and_client + api.stop_sandbox("sandbox-123") + client.stop_sandbox_with_options.assert_called_once() + + def test_get_sandbox(self, api_and_client): + api, client = api_and_client + api.get_sandbox("sandbox-123") + client.get_sandbox_with_options.assert_called_once() + + def test_list_sandboxes(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListSandboxesRequest) + api.list_sandboxes(input_data) + client.list_sandboxes_with_options.assert_called_once() + + +class TestSandboxControlAPIAsyncSignatures: + """测试 SandboxControlAPI 异步方法调用是否匹配 SDK 签名""" + + @pytest.mark.asyncio + async def test_create_template_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateTemplateInput) + await api.create_template_async(input_data) + client.create_template_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_delete_template_async(self, api_and_client): + api, client = api_and_client + await api.delete_template_async("test-template") + client.delete_template_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_update_template_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=UpdateTemplateInput) + await api.update_template_async("test-template", input_data) + client.update_template_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_get_template_async(self, api_and_client): + api, client = api_and_client + await api.get_template_async("test-template") + client.get_template_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_list_templates_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListTemplatesRequest) + await api.list_templates_async(input_data) + client.list_templates_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_create_sandbox_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=CreateSandboxInput) + await api.create_sandbox_async(input_data) + client.create_sandbox_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_stop_sandbox_async(self, api_and_client): + api, client = api_and_client + await api.stop_sandbox_async("sandbox-123") + client.stop_sandbox_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_get_sandbox_async(self, api_and_client): + api, client = api_and_client + await api.get_sandbox_async("sandbox-123") + client.get_sandbox_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_list_sandboxes_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListSandboxesRequest) + await api.list_sandboxes_async(input_data) + client.list_sandboxes_with_options_async.assert_called_once() diff --git a/tests/unittests/tool/api/__init__.py b/tests/unittests/tool/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unittests/tool/api/test_control.py b/tests/unittests/tool/api/test_control.py new file mode 100644 index 0000000..1b8c583 --- /dev/null +++ b/tests/unittests/tool/api/test_control.py @@ -0,0 +1,59 @@ +""" +测试 ToolControlAPI (tool) 对底层 SDK client 的调用是否与 SDK 方法签名匹配。 +""" + +from unittest.mock import create_autospec, MagicMock, patch + +from alibabacloud_agentrun20250910.client import Client as AgentRunClient +import pytest + +from agentrun.tool.api.control import ToolControlAPI +from agentrun.utils.config import Config + + +@pytest.fixture +def mock_config(): + return Config( + access_key_id="test-ak", + access_key_secret="test-sk", + region_id="cn-hangzhou", + control_endpoint="https://agentrun.cn-hangzhou.aliyuncs.com", + ) + + +@pytest.fixture +def mock_response(): + response = MagicMock() + response.body.request_id = "test-request-id" + response.body.data = MagicMock() + return response + + +@pytest.fixture +def api_and_client(mock_config, mock_response): + api = ToolControlAPI(config=mock_config) + mock_client = create_autospec(AgentRunClient, instance=True) + + for attr in dir(AgentRunClient): + if "with_options" in attr: + getattr(mock_client, attr).return_value = mock_response + + with patch.object(api, "_get_client", return_value=mock_client): + yield api, mock_client + + +class TestToolControlAPISignatures: + + def test_get_tool(self, api_and_client): + api, client = api_and_client + api.get_tool("test-tool") + client.get_tool_with_options.assert_called_once() + + +class TestToolControlAPIAsyncSignatures: + + @pytest.mark.asyncio + async def test_get_tool_async(self, api_and_client): + api, client = api_and_client + await api.get_tool_async("test-tool") + client.get_tool_with_options_async.assert_called_once() diff --git a/tests/unittests/toolset/api/test_control.py b/tests/unittests/toolset/api/test_control.py new file mode 100644 index 0000000..15e1fc8 --- /dev/null +++ b/tests/unittests/toolset/api/test_control.py @@ -0,0 +1,74 @@ +""" +测试 ToolControlAPI (toolset) 对底层 SDK client 的调用是否与 SDK 方法签名匹配。 + +注意:toolset 使用 DevsClient 而非 AgentRunClient。 +""" + +from unittest.mock import create_autospec, MagicMock, patch + +from alibabacloud_devs20230714.client import Client as DevsClient +from alibabacloud_devs20230714.models import ListToolsetsRequest +import pytest + +from agentrun.toolset.api.control import ToolControlAPI +from agentrun.utils.config import Config + + +@pytest.fixture +def mock_config(): + return Config( + access_key_id="test-ak", + access_key_secret="test-sk", + region_id="cn-hangzhou", + devs_endpoint="https://devs.cn-hangzhou.aliyuncs.com", + ) + + +@pytest.fixture +def mock_response(): + response = MagicMock() + response.body = MagicMock() + return response + + +@pytest.fixture +def api_and_client(mock_config, mock_response): + api = ToolControlAPI(config=mock_config) + mock_client = create_autospec(DevsClient, instance=True) + + for attr in dir(DevsClient): + if "with_options" in attr: + getattr(mock_client, attr).return_value = mock_response + + with patch.object(api, "_get_devs_client", return_value=mock_client): + yield api, mock_client + + +class TestToolsetControlAPISignatures: + + def test_get_toolset(self, api_and_client): + api, client = api_and_client + api.get_toolset("test-toolset") + client.get_toolset_with_options.assert_called_once() + + def test_list_toolsets(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListToolsetsRequest) + api.list_toolsets(input_data) + client.list_toolsets_with_options.assert_called_once() + + +class TestToolsetControlAPIAsyncSignatures: + + @pytest.mark.asyncio + async def test_get_toolset_async(self, api_and_client): + api, client = api_and_client + await api.get_toolset_async("test-toolset") + client.get_toolset_with_options_async.assert_called_once() + + @pytest.mark.asyncio + async def test_list_toolsets_async(self, api_and_client): + api, client = api_and_client + input_data = MagicMock(spec=ListToolsetsRequest) + await api.list_toolsets_async(input_data) + client.list_toolsets_with_options_async.assert_called_once()