mirror of https://github.com/alibaba/nacos.git
[ISSUE#13322] Add unit test for agent registration. (#13836)
This commit is contained in:
parent
f71257e390
commit
804fac3c6e
|
@ -0,0 +1,428 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.nacos.ai.controller;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;
|
||||||
|
import com.alibaba.nacos.ai.service.a2a.A2aServerOperationService;
|
||||||
|
import com.alibaba.nacos.api.ai.constant.AiConstants;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCard;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;
|
||||||
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
|
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||||
|
import com.alibaba.nacos.api.model.Page;
|
||||||
|
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||||
|
import com.alibaba.nacos.api.model.v2.Result;
|
||||||
|
import com.alibaba.nacos.core.model.form.PageForm;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.alibaba.nacos.ai.constant.Constants.MCP_LIST_SEARCH_BLUR;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.doNothing;
|
||||||
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for A2aAdminController.
|
||||||
|
*
|
||||||
|
* @author nacos
|
||||||
|
*/
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class A2aAdminControllerTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private A2aServerOperationService a2aServerOperationService;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private A2aAdminController a2aAdminController;
|
||||||
|
|
||||||
|
private AgentCardForm agentCardForm;
|
||||||
|
|
||||||
|
private AgentForm agentForm;
|
||||||
|
|
||||||
|
private AgentCardUpdateForm agentCardUpdateForm;
|
||||||
|
|
||||||
|
private AgentListForm agentListForm;
|
||||||
|
|
||||||
|
private PageForm pageForm;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
agentCardForm = new AgentCardForm();
|
||||||
|
agentCardForm.setAgentName("test-agent");
|
||||||
|
agentCardForm.setNamespaceId("public");
|
||||||
|
agentCardForm.setVersion("1.0.0");
|
||||||
|
agentCardForm.setRegistrationType(AiConstants.A2a.A2A_ENDPOINT_TYPE_URL);
|
||||||
|
agentCardForm.setAgentCard(
|
||||||
|
"{\"name\":\"test-agent\",\"version\":\"1.0.0\",\"protocolVersion\":\"1.0\",\"preferredTransport\":\"JSONRPC\",\"description\":\"Test agent description\",\"url\":\"http://test-agent.example.com\"}");
|
||||||
|
|
||||||
|
agentForm = new AgentForm();
|
||||||
|
agentForm.setAgentName("test-agent");
|
||||||
|
agentForm.setNamespaceId("public");
|
||||||
|
agentForm.setVersion("1.0.0");
|
||||||
|
agentForm.setRegistrationType(AiConstants.A2a.A2A_ENDPOINT_TYPE_URL);
|
||||||
|
|
||||||
|
agentCardUpdateForm = new AgentCardUpdateForm();
|
||||||
|
agentCardUpdateForm.setAgentName("test-agent");
|
||||||
|
agentCardUpdateForm.setNamespaceId("public");
|
||||||
|
agentCardUpdateForm.setVersion("1.0.0");
|
||||||
|
agentCardUpdateForm.setSetAsLatest(true);
|
||||||
|
agentCardUpdateForm.setRegistrationType(AiConstants.A2a.A2A_ENDPOINT_TYPE_URL);
|
||||||
|
agentCardUpdateForm.setAgentCard(
|
||||||
|
"{\"name\":\"test-agent\",\"version\":\"1.0.0\",\"protocolVersion\":\"1.0\",\"preferredTransport\":\"JSONRPC\",\"description\":\"Updated description\",\"url\":\"http://test-agent.example.com\"}");
|
||||||
|
|
||||||
|
agentListForm = new AgentListForm();
|
||||||
|
agentListForm.setAgentName("test-agent");
|
||||||
|
agentListForm.setNamespaceId("public");
|
||||||
|
agentListForm.setSearch(MCP_LIST_SEARCH_BLUR);
|
||||||
|
|
||||||
|
pageForm = new PageForm();
|
||||||
|
pageForm.setPageNo(1);
|
||||||
|
pageForm.setPageSize(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRegisterAgentSuccess() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
doNothing().when(a2aServerOperationService).registerAgent(any(AgentCard.class), anyString(), anyString());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Result<String> result = a2aAdminController.registerAgent(agentCardForm);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals("ok", result.getData());
|
||||||
|
verify(a2aServerOperationService).registerAgent(any(AgentCard.class), anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRegisterAgentValidationFailure() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
AgentCardForm invalidForm = new AgentCardForm();
|
||||||
|
// Missing required name field
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aAdminController.registerAgent(invalidForm));
|
||||||
|
verify(a2aServerOperationService, never()).registerAgent(any(AgentCard.class), anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRegisterAgentServiceException() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
NacosException exception = new NacosException(NacosException.SERVER_ERROR, "Registration failed");
|
||||||
|
doThrow(exception).when(a2aServerOperationService)
|
||||||
|
.registerAgent(any(AgentCard.class), anyString(), anyString());
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosException.class, () -> a2aAdminController.registerAgent(agentCardForm));
|
||||||
|
verify(a2aServerOperationService).registerAgent(any(AgentCard.class), anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetAgentCardSuccess() throws NacosApiException {
|
||||||
|
// Arrange
|
||||||
|
AgentCardDetailInfo expectedAgentCard = new AgentCardDetailInfo();
|
||||||
|
expectedAgentCard.setName("test-agent");
|
||||||
|
expectedAgentCard.setVersion("1.0.0");
|
||||||
|
expectedAgentCard.setProtocolVersion("1.0");
|
||||||
|
expectedAgentCard.setPreferredTransport("JSONRPC");
|
||||||
|
expectedAgentCard.setDescription("Test agent description");
|
||||||
|
|
||||||
|
when(a2aServerOperationService.getAgentCard(anyString(), anyString(), anyString(), anyString())).thenReturn(
|
||||||
|
expectedAgentCard);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Result<AgentCardDetailInfo> result = a2aAdminController.getAgentCard(agentForm);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(expectedAgentCard, result.getData());
|
||||||
|
verify(a2aServerOperationService).getAgentCard(anyString(), anyString(), anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetAgentCardValidationFailure() throws NacosApiException {
|
||||||
|
// Arrange
|
||||||
|
AgentForm invalidForm = new AgentForm();
|
||||||
|
// Missing required fields
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aAdminController.getAgentCard(invalidForm));
|
||||||
|
verify(a2aServerOperationService, never()).getAgentCard(anyString(), anyString(), anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetAgentCardServiceException() throws NacosApiException {
|
||||||
|
// Arrange
|
||||||
|
NacosApiException exception = new NacosApiException(NacosException.SERVER_ERROR, ErrorCode.RESOURCE_NOT_FOUND,
|
||||||
|
"Agent not found");
|
||||||
|
when(a2aServerOperationService.getAgentCard(anyString(), anyString(), anyString(), anyString())).thenThrow(
|
||||||
|
exception);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aAdminController.getAgentCard(agentForm));
|
||||||
|
verify(a2aServerOperationService).getAgentCard(anyString(), anyString(), anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateAgentCardSuccess() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
doNothing().when(a2aServerOperationService)
|
||||||
|
.updateAgentCard(any(AgentCard.class), anyString(), anyString(), anyBoolean());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Result<String> result = a2aAdminController.updateAgentCard(agentCardUpdateForm);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals("ok", result.getData());
|
||||||
|
verify(a2aServerOperationService).updateAgentCard(any(AgentCard.class), anyString(), anyString(), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateAgentCardValidationFailure() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
AgentCardUpdateForm invalidForm = new AgentCardUpdateForm();
|
||||||
|
// Missing required name field
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aAdminController.updateAgentCard(invalidForm));
|
||||||
|
verify(a2aServerOperationService, never()).updateAgentCard(any(AgentCard.class), anyString(), anyString(),
|
||||||
|
anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateAgentCardServiceException() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
NacosException exception = new NacosException(NacosException.SERVER_ERROR, "Update failed");
|
||||||
|
doThrow(exception).when(a2aServerOperationService)
|
||||||
|
.updateAgentCard(any(AgentCard.class), anyString(), anyString(), anyBoolean());
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosException.class, () -> a2aAdminController.updateAgentCard(agentCardUpdateForm));
|
||||||
|
verify(a2aServerOperationService).updateAgentCard(any(AgentCard.class), anyString(), anyString(), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAgentSuccess() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
doNothing().when(a2aServerOperationService).deleteAgent(anyString(), anyString(), anyString());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Result<String> result = a2aAdminController.deleteAgent(agentForm);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals("ok", result.getData());
|
||||||
|
verify(a2aServerOperationService).deleteAgent(anyString(), anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAgentValidationFailure() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
AgentForm invalidForm = new AgentForm();
|
||||||
|
// Missing required fields
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aAdminController.deleteAgent(invalidForm));
|
||||||
|
verify(a2aServerOperationService, never()).deleteAgent(anyString(), anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAgentServiceException() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
NacosException exception = new NacosException(NacosException.SERVER_ERROR, "Delete failed");
|
||||||
|
doThrow(exception).when(a2aServerOperationService).deleteAgent(anyString(), anyString(), anyString());
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosException.class, () -> a2aAdminController.deleteAgent(agentForm));
|
||||||
|
verify(a2aServerOperationService).deleteAgent(anyString(), anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgentsSuccess() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
AgentCardVersionInfo agent1 = new AgentCardVersionInfo();
|
||||||
|
agent1.setName("agent1");
|
||||||
|
agent1.setLatestPublishedVersion("1.0.0");
|
||||||
|
|
||||||
|
AgentCardVersionInfo agent2 = new AgentCardVersionInfo();
|
||||||
|
agent2.setName("agent2");
|
||||||
|
agent2.setLatestPublishedVersion("2.0.0");
|
||||||
|
|
||||||
|
List<AgentCardVersionInfo> agentList = Arrays.asList(agent1, agent2);
|
||||||
|
Page<AgentCardVersionInfo> expectedPage = new Page<>();
|
||||||
|
expectedPage.setPageItems(agentList);
|
||||||
|
expectedPage.setTotalCount(2);
|
||||||
|
expectedPage.setPageNumber(1);
|
||||||
|
expectedPage.setPagesAvailable(1);
|
||||||
|
|
||||||
|
when(a2aServerOperationService.listAgents(anyString(), anyString(), anyString(), anyInt(),
|
||||||
|
anyInt())).thenReturn(expectedPage);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Result<Page<AgentCardVersionInfo>> result = a2aAdminController.listAgents(agentListForm, pageForm);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(expectedPage, result.getData());
|
||||||
|
assertEquals(2, result.getData().getTotalCount());
|
||||||
|
assertEquals(2, result.getData().getPageItems().size());
|
||||||
|
verify(a2aServerOperationService).listAgents(anyString(), anyString(), anyString(), anyInt(), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgentsAgentListFormValidationFailure() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
AgentListForm invalidForm = new AgentListForm();
|
||||||
|
// Missing required fields
|
||||||
|
PageForm validPageForm = new PageForm();
|
||||||
|
validPageForm.setPageNo(1);
|
||||||
|
validPageForm.setPageSize(10);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aAdminController.listAgents(invalidForm, validPageForm));
|
||||||
|
verify(a2aServerOperationService, never()).listAgents(anyString(), anyString(), anyString(), anyInt(),
|
||||||
|
anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgentsPageFormValidationFailure() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
AgentListForm validAgentListForm = new AgentListForm();
|
||||||
|
validAgentListForm.setAgentName("test-agent");
|
||||||
|
validAgentListForm.setNamespaceId("public");
|
||||||
|
validAgentListForm.setSearch(MCP_LIST_SEARCH_BLUR);
|
||||||
|
|
||||||
|
PageForm invalidPageForm = new PageForm();
|
||||||
|
invalidPageForm.setPageNo(0); // Invalid page number
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aAdminController.listAgents(validAgentListForm, invalidPageForm));
|
||||||
|
verify(a2aServerOperationService, never()).listAgents(anyString(), anyString(), anyString(), anyInt(),
|
||||||
|
anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgentsServiceException() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
NacosException exception = new NacosException(NacosException.SERVER_ERROR, "List failed");
|
||||||
|
when(a2aServerOperationService.listAgents(anyString(), anyString(), anyString(), anyInt(), anyInt())).thenThrow(
|
||||||
|
exception);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosException.class, () -> a2aAdminController.listAgents(agentListForm, pageForm));
|
||||||
|
verify(a2aServerOperationService).listAgents(anyString(), anyString(), anyString(), anyInt(), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgentVersionsSuccess() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
AgentVersionDetail version1 = new AgentVersionDetail();
|
||||||
|
version1.setVersion("1.0.0");
|
||||||
|
version1.setLatest(true);
|
||||||
|
|
||||||
|
AgentVersionDetail version2 = new AgentVersionDetail();
|
||||||
|
version2.setVersion("2.0.0");
|
||||||
|
version2.setLatest(false);
|
||||||
|
|
||||||
|
List<AgentVersionDetail> versionList = Arrays.asList(version1, version2);
|
||||||
|
|
||||||
|
when(a2aServerOperationService.listAgentVersions(anyString(), anyString())).thenReturn(versionList);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Result<List<AgentVersionDetail>> result = a2aAdminController.listAgentVersions(agentForm);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(versionList, result.getData());
|
||||||
|
assertEquals(2, result.getData().size());
|
||||||
|
verify(a2aServerOperationService).listAgentVersions(anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgentVersionsValidationFailure() throws NacosApiException {
|
||||||
|
// Arrange
|
||||||
|
AgentForm invalidForm = new AgentForm();
|
||||||
|
// Missing required fields
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aAdminController.listAgentVersions(invalidForm));
|
||||||
|
verify(a2aServerOperationService, never()).listAgentVersions(anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgentVersionsEmptyResult() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
List<AgentVersionDetail> emptyList = Arrays.asList();
|
||||||
|
when(a2aServerOperationService.listAgentVersions(anyString(), anyString())).thenReturn(emptyList);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Result<List<AgentVersionDetail>> result = a2aAdminController.listAgentVersions(agentForm);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(emptyList, result.getData());
|
||||||
|
assertEquals(0, result.getData().size());
|
||||||
|
verify(a2aServerOperationService).listAgentVersions(anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgentsEmptyResult() throws NacosException {
|
||||||
|
// Arrange
|
||||||
|
List<AgentCardVersionInfo> emptyList = Arrays.asList();
|
||||||
|
Page<AgentCardVersionInfo> emptyPage = new Page<>();
|
||||||
|
emptyPage.setPageItems(emptyList);
|
||||||
|
emptyPage.setTotalCount(0);
|
||||||
|
emptyPage.setPageNumber(1);
|
||||||
|
emptyPage.setPagesAvailable(1);
|
||||||
|
|
||||||
|
when(a2aServerOperationService.listAgents(anyString(), anyString(), anyString(), anyInt(),
|
||||||
|
anyInt())).thenReturn(emptyPage);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Result<Page<AgentCardVersionInfo>> result = a2aAdminController.listAgents(agentListForm, pageForm);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(emptyPage, result.getData());
|
||||||
|
assertEquals(0, result.getData().getTotalCount());
|
||||||
|
assertEquals(0, result.getData().getPageItems().size());
|
||||||
|
verify(a2aServerOperationService).listAgents(anyString(), anyString(), anyString(), anyInt(), anyInt());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,338 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.nacos.ai.service.a2a;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.ai.constant.Constants;
|
||||||
|
import com.alibaba.nacos.ai.service.SyncEffectService;
|
||||||
|
import com.alibaba.nacos.ai.service.a2a.identity.AgentIdCodecHolder;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCard;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentProvider;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;
|
||||||
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
|
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||||
|
import com.alibaba.nacos.api.model.Page;
|
||||||
|
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||||
|
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
||||||
|
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||||
|
import com.alibaba.nacos.config.server.exception.ConfigAlreadyExistsException;
|
||||||
|
import com.alibaba.nacos.config.server.model.ConfigInfo;
|
||||||
|
import com.alibaba.nacos.config.server.model.ConfigRequestInfo;
|
||||||
|
import com.alibaba.nacos.config.server.model.form.ConfigForm;
|
||||||
|
import com.alibaba.nacos.config.server.service.ConfigDetailService;
|
||||||
|
import com.alibaba.nacos.config.server.service.ConfigOperationService;
|
||||||
|
import com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;
|
||||||
|
import com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;
|
||||||
|
import com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;
|
||||||
|
import com.alibaba.nacos.naming.core.v2.index.ServiceStorage;
|
||||||
|
import com.alibaba.nacos.naming.core.v2.pojo.Service;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import org.mockito.junit.jupiter.MockitoSettings;
|
||||||
|
import org.mockito.quality.Strictness;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.doNothing;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for A2aServerOperationServiceTest.
|
||||||
|
*
|
||||||
|
* @author nacos
|
||||||
|
*/
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||||
|
public class A2aServerOperationServiceTest {
|
||||||
|
|
||||||
|
private static final String TEST_NAMESPACE_ID = "test-namespace";
|
||||||
|
|
||||||
|
private static final String TEST_AGENT_NAME = "test-agent";
|
||||||
|
|
||||||
|
private static final String TEST_AGENT_VERSION = "1.0.0";
|
||||||
|
|
||||||
|
private static final String TEST_REGISTRATION_TYPE = "service";
|
||||||
|
|
||||||
|
private static final String ENCODED_AGENT_NAME = "encoded-test-agent";
|
||||||
|
|
||||||
|
private static final String ENCODED_AGENT_NAME_WITH_VERSION = ENCODED_AGENT_NAME + "-" + TEST_AGENT_VERSION;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ConfigQueryChainService configQueryChainService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ConfigOperationService configOperationService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ConfigDetailService configDetailService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private SyncEffectService syncEffectService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private AgentIdCodecHolder agentIdCodecHolder;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ServiceStorage serviceStorage;
|
||||||
|
|
||||||
|
private A2aServerOperationService a2aServerOperationService;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
a2aServerOperationService = new A2aServerOperationService(configQueryChainService, configOperationService,
|
||||||
|
configDetailService, syncEffectService, serviceStorage, agentIdCodecHolder);
|
||||||
|
|
||||||
|
when(agentIdCodecHolder.encode(anyString())).thenReturn(ENCODED_AGENT_NAME);
|
||||||
|
when(agentIdCodecHolder.encodeForSearch(anyString())).thenReturn(ENCODED_AGENT_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRegisterAgentSuccess() throws NacosException {
|
||||||
|
final AgentCard agentCard = buildTestAgentCard();
|
||||||
|
|
||||||
|
ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);
|
||||||
|
when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);
|
||||||
|
when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);
|
||||||
|
|
||||||
|
when(configOperationService.publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class), eq(null))).thenReturn(true);
|
||||||
|
doNothing().when(syncEffectService).toSync(any(ConfigForm.class), anyLong());
|
||||||
|
|
||||||
|
a2aServerOperationService.registerAgent(agentCard, TEST_NAMESPACE_ID, TEST_REGISTRATION_TYPE);
|
||||||
|
|
||||||
|
verify(configOperationService, times(2)).publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class), eq(null));
|
||||||
|
verify(syncEffectService, times(1)).toSync(any(ConfigForm.class), anyLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRegisterAgentAlreadyExists() throws NacosException {
|
||||||
|
AgentCard agentCard = buildTestAgentCard();
|
||||||
|
|
||||||
|
ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);
|
||||||
|
when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);
|
||||||
|
when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);
|
||||||
|
|
||||||
|
when(configOperationService.publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class), eq(null)))
|
||||||
|
.thenThrow(new ConfigAlreadyExistsException("Config already exists"));
|
||||||
|
|
||||||
|
NacosApiException exception = assertThrows(NacosApiException.class, () -> {
|
||||||
|
a2aServerOperationService.registerAgent(agentCard, TEST_NAMESPACE_ID, TEST_REGISTRATION_TYPE);
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals(NacosException.CONFLICT, exception.getErrCode());
|
||||||
|
assertEquals(ErrorCode.RESOURCE_CONFLICT.getCode(), exception.getDetailErrCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAgentSuccess() throws NacosException {
|
||||||
|
AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();
|
||||||
|
ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);
|
||||||
|
|
||||||
|
when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);
|
||||||
|
when(response.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));
|
||||||
|
when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);
|
||||||
|
|
||||||
|
when(configOperationService.deleteConfig(eq(ENCODED_AGENT_NAME_WITH_VERSION),
|
||||||
|
eq(Constants.A2A.AGENT_VERSION_GROUP), eq(TEST_NAMESPACE_ID), eq(null), eq(null), eq("nacos"), eq(null))).thenReturn(true);
|
||||||
|
|
||||||
|
a2aServerOperationService.deleteAgent(TEST_NAMESPACE_ID, TEST_AGENT_NAME, TEST_AGENT_VERSION);
|
||||||
|
|
||||||
|
verify(configOperationService, times(1)).deleteConfig(eq(ENCODED_AGENT_NAME_WITH_VERSION),
|
||||||
|
eq(Constants.A2A.AGENT_VERSION_GROUP), eq(TEST_NAMESPACE_ID), eq(null), eq(null), eq("nacos"), eq(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAgentWhenAgentNotFound() throws NacosException {
|
||||||
|
ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);
|
||||||
|
when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);
|
||||||
|
when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);
|
||||||
|
|
||||||
|
a2aServerOperationService.deleteAgent(TEST_NAMESPACE_ID, TEST_AGENT_NAME, TEST_AGENT_VERSION);
|
||||||
|
|
||||||
|
verify(configOperationService, times(0)).deleteConfig(anyString(), anyString(), anyString(), any(), any(),
|
||||||
|
anyString(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateAgentCardSuccess() throws NacosException {
|
||||||
|
final AgentCard agentCard = buildTestAgentCard();
|
||||||
|
|
||||||
|
ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);
|
||||||
|
when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);
|
||||||
|
when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(buildTestAgentCardVersionInfo()));
|
||||||
|
|
||||||
|
ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);
|
||||||
|
when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);
|
||||||
|
when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(buildTestAgentCardDetailInfo()));
|
||||||
|
|
||||||
|
when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))
|
||||||
|
.thenReturn(versionResponse)
|
||||||
|
.thenReturn(detailResponse);
|
||||||
|
|
||||||
|
when(configOperationService.publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class), eq(null))).thenReturn(true);
|
||||||
|
doNothing().when(syncEffectService).toSync(any(ConfigForm.class), anyLong());
|
||||||
|
|
||||||
|
a2aServerOperationService.updateAgentCard(agentCard, TEST_NAMESPACE_ID, TEST_REGISTRATION_TYPE, true);
|
||||||
|
|
||||||
|
verify(configOperationService, times(2)).publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class), eq(null));
|
||||||
|
verify(syncEffectService, times(1)).toSync(any(ConfigForm.class), anyLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgentsSuccess() throws NacosException {
|
||||||
|
Page<ConfigInfo> configPage = new Page<>();
|
||||||
|
ConfigInfo configInfo = new ConfigInfo();
|
||||||
|
AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();
|
||||||
|
configInfo.setContent(JacksonUtils.toJson(versionInfo));
|
||||||
|
configPage.setPageItems(Collections.singletonList(configInfo));
|
||||||
|
configPage.setTotalCount(1);
|
||||||
|
|
||||||
|
when(configDetailService.findConfigInfoPage(eq(Constants.A2A.SEARCH_BLUR), eq(1), eq(10), anyString(),
|
||||||
|
eq(Constants.A2A.AGENT_GROUP), eq(TEST_NAMESPACE_ID), eq(null))).thenReturn(configPage);
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> result = a2aServerOperationService.listAgents(TEST_NAMESPACE_ID, TEST_AGENT_NAME,
|
||||||
|
Constants.A2A.SEARCH_BLUR, 1, 10);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(1, result.getTotalCount());
|
||||||
|
assertEquals(1, result.getPageItems().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgentVersionsSuccess() throws NacosApiException {
|
||||||
|
AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();
|
||||||
|
ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);
|
||||||
|
when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);
|
||||||
|
when(response.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));
|
||||||
|
when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);
|
||||||
|
|
||||||
|
List<AgentVersionDetail> result = a2aServerOperationService.listAgentVersions(TEST_NAMESPACE_ID, TEST_AGENT_NAME);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetAgentCardSuccess() throws NacosApiException {
|
||||||
|
AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();
|
||||||
|
AgentCardDetailInfo detailInfo = buildTestAgentCardDetailInfo();
|
||||||
|
|
||||||
|
ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);
|
||||||
|
when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);
|
||||||
|
when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));
|
||||||
|
|
||||||
|
ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);
|
||||||
|
when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);
|
||||||
|
when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(detailInfo));
|
||||||
|
|
||||||
|
// Mock service storage for endpoint injection
|
||||||
|
Service service = Service.newService(TEST_NAMESPACE_ID, Constants.A2A.AGENT_ENDPOINT_GROUP,
|
||||||
|
ENCODED_AGENT_NAME + "::" + TEST_AGENT_VERSION);
|
||||||
|
ServiceInfo serviceInfo = new ServiceInfo();
|
||||||
|
serviceInfo.setHosts(Collections.emptyList());
|
||||||
|
when(serviceStorage.getData(service)).thenReturn(serviceInfo);
|
||||||
|
|
||||||
|
when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))
|
||||||
|
.thenReturn(versionResponse)
|
||||||
|
.thenReturn(detailResponse);
|
||||||
|
|
||||||
|
AgentCardDetailInfo result = a2aServerOperationService.getAgentCard(TEST_NAMESPACE_ID, TEST_AGENT_NAME,
|
||||||
|
TEST_AGENT_VERSION, TEST_REGISTRATION_TYPE);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(TEST_AGENT_NAME, result.getName());
|
||||||
|
assertEquals(TEST_AGENT_VERSION, result.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetAgentCardNotFound() throws NacosApiException {
|
||||||
|
AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();
|
||||||
|
|
||||||
|
ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);
|
||||||
|
when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);
|
||||||
|
when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));
|
||||||
|
|
||||||
|
ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);
|
||||||
|
when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);
|
||||||
|
|
||||||
|
when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))
|
||||||
|
.thenReturn(versionResponse)
|
||||||
|
.thenReturn(detailResponse);
|
||||||
|
|
||||||
|
NacosApiException exception = assertThrows(NacosApiException.class, () -> {
|
||||||
|
a2aServerOperationService.getAgentCard(TEST_NAMESPACE_ID, TEST_AGENT_NAME, TEST_AGENT_VERSION,
|
||||||
|
TEST_REGISTRATION_TYPE);
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals(NacosException.NOT_FOUND, exception.getErrCode());
|
||||||
|
assertEquals(ErrorCode.AGENT_VERSION_NOT_FOUND.getCode(), exception.getDetailErrCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
private AgentCard buildTestAgentCard() {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
agentCard.setName(TEST_AGENT_NAME);
|
||||||
|
agentCard.setVersion(TEST_AGENT_VERSION);
|
||||||
|
agentCard.setDescription("Test Agent Description");
|
||||||
|
AgentProvider agentProvider = new AgentProvider();
|
||||||
|
agentProvider.setOrganization("Test Organization");
|
||||||
|
agentCard.setProvider(agentProvider);
|
||||||
|
agentCard.setPreferredTransport("http");
|
||||||
|
return agentCard;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AgentCardDetailInfo buildTestAgentCardDetailInfo() {
|
||||||
|
AgentCardDetailInfo detailInfo = new AgentCardDetailInfo();
|
||||||
|
detailInfo.setName(TEST_AGENT_NAME);
|
||||||
|
detailInfo.setVersion(TEST_AGENT_VERSION);
|
||||||
|
detailInfo.setDescription("Test Agent Description");
|
||||||
|
AgentProvider agentProvider = new AgentProvider();
|
||||||
|
agentProvider.setOrganization("Test Organization");
|
||||||
|
detailInfo.setProvider(agentProvider);
|
||||||
|
detailInfo.setRegistrationType(TEST_REGISTRATION_TYPE);
|
||||||
|
return detailInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AgentCardVersionInfo buildTestAgentCardVersionInfo() {
|
||||||
|
AgentCardVersionInfo versionInfo = new AgentCardVersionInfo();
|
||||||
|
versionInfo.setName(TEST_AGENT_NAME);
|
||||||
|
versionInfo.setVersion(TEST_AGENT_VERSION);
|
||||||
|
versionInfo.setLatestPublishedVersion(TEST_AGENT_VERSION);
|
||||||
|
versionInfo.setRegistrationType(TEST_REGISTRATION_TYPE);
|
||||||
|
|
||||||
|
AgentVersionDetail versionDetail = new AgentVersionDetail();
|
||||||
|
versionDetail.setVersion(TEST_AGENT_VERSION);
|
||||||
|
versionDetail.setLatest(true);
|
||||||
|
versionInfo.setVersionDetails(Collections.singletonList(versionDetail));
|
||||||
|
|
||||||
|
return versionInfo;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,224 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.nacos.console.controller.v3.ai;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.ai.constant.Constants;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;
|
||||||
|
import com.alibaba.nacos.ai.utils.AgentRequestUtil;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCard;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;
|
||||||
|
import com.alibaba.nacos.api.model.Page;
|
||||||
|
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||||
|
import com.alibaba.nacos.api.model.v2.Result;
|
||||||
|
import com.alibaba.nacos.auth.config.NacosAuthConfig;
|
||||||
|
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||||
|
import com.alibaba.nacos.console.proxy.ai.A2aProxy;
|
||||||
|
import com.alibaba.nacos.core.auth.AuthFilter;
|
||||||
|
import com.alibaba.nacos.core.model.form.PageForm;
|
||||||
|
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockedStatic;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||||
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.mockStatic;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for ConsoleA2aControllerTest.
|
||||||
|
*
|
||||||
|
* @author nacos
|
||||||
|
*/
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
public class ConsoleA2aControllerTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private A2aProxy a2aProxy;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private NacosAuthConfig authConfig;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private AuthFilter authFilter;
|
||||||
|
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
private ConsoleA2aController consoleA2aController;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
EnvUtil.setEnvironment(new StandardEnvironment());
|
||||||
|
consoleA2aController = new ConsoleA2aController(a2aProxy);
|
||||||
|
mockMvc = MockMvcBuilders.standaloneSetup(consoleA2aController).addFilter(authFilter).build();
|
||||||
|
when(authConfig.isAuthEnabled()).thenReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRegisterAgent() throws Exception {
|
||||||
|
String agentCardJson = "{\"name\":\"test-agent\",\"version\":\"1.0.0\",\"protocolVersion\":\"1.0\",\"preferredTransport\":\"http\",\"url\":\"http://localhost:8080\"}";
|
||||||
|
|
||||||
|
try (MockedStatic<AgentRequestUtil> mockedUtil = mockStatic(AgentRequestUtil.class)) {
|
||||||
|
AgentCard mockAgentCard = new AgentCard();
|
||||||
|
mockAgentCard.setName("test-agent");
|
||||||
|
mockedUtil.when(() -> AgentRequestUtil.parseAgentCard(any(AgentCardForm.class))).thenReturn(mockAgentCard);
|
||||||
|
|
||||||
|
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(Constants.A2A.CONSOLE_PATH)
|
||||||
|
.param("namespaceId", "test-namespace")
|
||||||
|
.param("agentName", "test-agent")
|
||||||
|
.param("agentCard", agentCardJson)
|
||||||
|
.param("registrationType", "SERVICE");
|
||||||
|
|
||||||
|
MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();
|
||||||
|
String actualValue = response.getContentAsString();
|
||||||
|
Result<String> result = JacksonUtils.toObj(actualValue, new TypeReference<>() { });
|
||||||
|
|
||||||
|
assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());
|
||||||
|
assertEquals("ok", result.getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetAgentCard() throws Exception {
|
||||||
|
AgentCardDetailInfo mockDetailInfo = new AgentCardDetailInfo();
|
||||||
|
mockDetailInfo.setName("test-agent");
|
||||||
|
mockDetailInfo.setVersion("1.0.0");
|
||||||
|
|
||||||
|
when(a2aProxy.getAgentCard(any(AgentForm.class))).thenReturn(mockDetailInfo);
|
||||||
|
|
||||||
|
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.A2A.CONSOLE_PATH)
|
||||||
|
.param("namespaceId", "test-namespace")
|
||||||
|
.param("agentName", "test-agent")
|
||||||
|
.param("version", "1.0.0")
|
||||||
|
.param("registrationType", "SERVICE");
|
||||||
|
|
||||||
|
MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();
|
||||||
|
String actualValue = response.getContentAsString();
|
||||||
|
Result<AgentCardDetailInfo> result = JacksonUtils.toObj(actualValue, new TypeReference<>() { });
|
||||||
|
|
||||||
|
assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());
|
||||||
|
assertEquals("test-agent", result.getData().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateAgentCard() throws Exception {
|
||||||
|
String agentCardJson = "{\"name\":\"test-agent\",\"version\":\"1.0.1\",\"protocolVersion\":\"1.0\",\"preferredTransport\":\"http\",\"url\":\"http://localhost:8080\"}";
|
||||||
|
|
||||||
|
try (MockedStatic<AgentRequestUtil> mockedUtil = mockStatic(AgentRequestUtil.class)) {
|
||||||
|
AgentCard mockAgentCard = new AgentCard();
|
||||||
|
mockAgentCard.setName("test-agent");
|
||||||
|
mockAgentCard.setVersion("1.0.1");
|
||||||
|
mockedUtil.when(() -> AgentRequestUtil.parseAgentCard(any(AgentCardUpdateForm.class))).thenReturn(mockAgentCard);
|
||||||
|
|
||||||
|
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.put(Constants.A2A.CONSOLE_PATH)
|
||||||
|
.param("namespaceId", "test-namespace")
|
||||||
|
.param("agentName", "test-agent")
|
||||||
|
.param("agentCard", agentCardJson)
|
||||||
|
.param("registrationType", "SERVICE")
|
||||||
|
.param("latest", "true");
|
||||||
|
|
||||||
|
MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();
|
||||||
|
String actualValue = response.getContentAsString();
|
||||||
|
Result<String> result = JacksonUtils.toObj(actualValue, new TypeReference<>() { });
|
||||||
|
|
||||||
|
assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());
|
||||||
|
assertEquals("ok", result.getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAgent() throws Exception {
|
||||||
|
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.A2A.CONSOLE_PATH)
|
||||||
|
.param("namespaceId", "test-namespace")
|
||||||
|
.param("agentName", "test-agent")
|
||||||
|
.param("version", "1.0.0")
|
||||||
|
.param("registrationType", "SERVICE");
|
||||||
|
|
||||||
|
MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();
|
||||||
|
String actualValue = response.getContentAsString();
|
||||||
|
Result<String> result = JacksonUtils.toObj(actualValue, new TypeReference<>() { });
|
||||||
|
|
||||||
|
assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());
|
||||||
|
assertEquals("ok", result.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgents() throws Exception {
|
||||||
|
Page<AgentCardVersionInfo> mockPage = new Page<>();
|
||||||
|
AgentCardVersionInfo versionInfo = new AgentCardVersionInfo();
|
||||||
|
versionInfo.setName("test-agent");
|
||||||
|
versionInfo.setVersion("1.0.0");
|
||||||
|
mockPage.setPageItems(Collections.singletonList(versionInfo));
|
||||||
|
mockPage.setTotalCount(1);
|
||||||
|
|
||||||
|
when(a2aProxy.listAgents(any(AgentListForm.class), any(PageForm.class))).thenReturn(mockPage);
|
||||||
|
|
||||||
|
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.A2A.CONSOLE_PATH + "/list")
|
||||||
|
.param("namespaceId", "test-namespace")
|
||||||
|
.param("agentName", "test")
|
||||||
|
.param("search", "blur")
|
||||||
|
.param("pageNo", "1")
|
||||||
|
.param("pageSize", "10");
|
||||||
|
|
||||||
|
MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();
|
||||||
|
String actualValue = response.getContentAsString();
|
||||||
|
Result<Page<AgentCardVersionInfo>> result = JacksonUtils.toObj(actualValue, new TypeReference<>() { });
|
||||||
|
|
||||||
|
assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());
|
||||||
|
assertEquals(1, result.getData().getTotalCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAgentVersions() throws Exception {
|
||||||
|
AgentVersionDetail versionDetail = new AgentVersionDetail();
|
||||||
|
versionDetail.setVersion("1.0.0");
|
||||||
|
versionDetail.setLatest(true);
|
||||||
|
|
||||||
|
when(a2aProxy.listAgentVersions("test-namespace", "test-agent")).thenReturn(Collections.singletonList(versionDetail));
|
||||||
|
|
||||||
|
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.A2A.CONSOLE_PATH + "/version/list")
|
||||||
|
.param("namespaceId", "test-namespace")
|
||||||
|
.param("agentName", "test-agent");
|
||||||
|
|
||||||
|
MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();
|
||||||
|
String actualValue = response.getContentAsString();
|
||||||
|
Result<List<AgentVersionDetail>> result = JacksonUtils.toObj(actualValue, new TypeReference<>() { });
|
||||||
|
|
||||||
|
assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());
|
||||||
|
assertEquals(1, result.getData().size());
|
||||||
|
assertEquals("1.0.0", result.getData().get(0).getVersion());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.nacos.console.handler.impl.inner.ai;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;
|
||||||
|
import com.alibaba.nacos.ai.service.a2a.A2aServerOperationService;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCard;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;
|
||||||
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
|
import com.alibaba.nacos.api.model.Page;
|
||||||
|
import com.alibaba.nacos.core.model.form.PageForm;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.doNothing;
|
||||||
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for A2aInnerHandler.
|
||||||
|
*
|
||||||
|
* @author nacos
|
||||||
|
*/
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
public class A2aInnerHandlerTest {
|
||||||
|
|
||||||
|
private static final String NAMESPACE_ID = "test-namespace";
|
||||||
|
|
||||||
|
private static final String AGENT_NAME = "test-agent";
|
||||||
|
|
||||||
|
private static final String AGENT_VERSION = "1.0.0";
|
||||||
|
|
||||||
|
private static final String REGISTRATION_TYPE = "service";
|
||||||
|
|
||||||
|
private static final String SEARCH_TYPE = "blur";
|
||||||
|
|
||||||
|
private static final int PAGE_NO = 1;
|
||||||
|
|
||||||
|
private static final int PAGE_SIZE = 10;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private A2aServerOperationService a2aServerOperationService;
|
||||||
|
|
||||||
|
private A2aInnerHandler a2aInnerHandler;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
a2aInnerHandler = new A2aInnerHandler(a2aServerOperationService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerAgent() throws NacosException {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
agentCard.setName(AGENT_NAME);
|
||||||
|
AgentCardForm agentCardForm = new AgentCardForm();
|
||||||
|
agentCardForm.setNamespaceId(NAMESPACE_ID);
|
||||||
|
agentCardForm.setRegistrationType(REGISTRATION_TYPE);
|
||||||
|
|
||||||
|
doNothing().when(a2aServerOperationService)
|
||||||
|
.registerAgent(eq(agentCard), eq(NAMESPACE_ID), eq(REGISTRATION_TYPE));
|
||||||
|
|
||||||
|
a2aInnerHandler.registerAgent(agentCard, agentCardForm);
|
||||||
|
|
||||||
|
verify(a2aServerOperationService).registerAgent(eq(agentCard), eq(NAMESPACE_ID), eq(REGISTRATION_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerAgentThrowsException() throws NacosException {
|
||||||
|
final AgentCard agentCard = new AgentCard();
|
||||||
|
AgentCardForm agentCardForm = new AgentCardForm();
|
||||||
|
agentCardForm.setNamespaceId(NAMESPACE_ID);
|
||||||
|
agentCardForm.setRegistrationType(REGISTRATION_TYPE);
|
||||||
|
|
||||||
|
NacosException expectedException = new NacosException(NacosException.CONFLICT, "Agent already exists");
|
||||||
|
doThrow(expectedException).when(a2aServerOperationService)
|
||||||
|
.registerAgent(any(AgentCard.class), any(String.class), any(String.class));
|
||||||
|
|
||||||
|
NacosException actualException = assertThrows(NacosException.class,
|
||||||
|
() -> a2aInnerHandler.registerAgent(agentCard, agentCardForm));
|
||||||
|
|
||||||
|
assertEquals(expectedException.getErrCode(), actualException.getErrCode());
|
||||||
|
verify(a2aServerOperationService).registerAgent(any(AgentCard.class), any(String.class), any(String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getAgentCardWithVersions() throws NacosException {
|
||||||
|
AgentForm form = new AgentForm();
|
||||||
|
form.setNamespaceId(NAMESPACE_ID);
|
||||||
|
form.setAgentName(AGENT_NAME);
|
||||||
|
form.setVersion(AGENT_VERSION);
|
||||||
|
form.setRegistrationType(REGISTRATION_TYPE);
|
||||||
|
|
||||||
|
AgentCardDetailInfo expectedDetailInfo = new AgentCardDetailInfo();
|
||||||
|
expectedDetailInfo.setName(AGENT_NAME);
|
||||||
|
expectedDetailInfo.setVersion(AGENT_VERSION);
|
||||||
|
|
||||||
|
when(a2aServerOperationService.getAgentCard(eq(NAMESPACE_ID), eq(AGENT_NAME), eq(AGENT_VERSION),
|
||||||
|
eq(REGISTRATION_TYPE))).thenReturn(expectedDetailInfo);
|
||||||
|
|
||||||
|
AgentCardDetailInfo actualDetailInfo = a2aInnerHandler.getAgentCardWithVersions(form);
|
||||||
|
|
||||||
|
assertEquals(expectedDetailInfo, actualDetailInfo);
|
||||||
|
verify(a2aServerOperationService).getAgentCard(eq(NAMESPACE_ID), eq(AGENT_NAME), eq(AGENT_VERSION),
|
||||||
|
eq(REGISTRATION_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deleteAgent() throws NacosException {
|
||||||
|
AgentForm form = new AgentForm();
|
||||||
|
form.setNamespaceId(NAMESPACE_ID);
|
||||||
|
form.setAgentName(AGENT_NAME);
|
||||||
|
form.setVersion(AGENT_VERSION);
|
||||||
|
|
||||||
|
doNothing().when(a2aServerOperationService).deleteAgent(eq(NAMESPACE_ID), eq(AGENT_NAME), eq(AGENT_VERSION));
|
||||||
|
|
||||||
|
a2aInnerHandler.deleteAgent(form);
|
||||||
|
|
||||||
|
verify(a2aServerOperationService).deleteAgent(eq(NAMESPACE_ID), eq(AGENT_NAME), eq(AGENT_VERSION));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateAgentCard() throws NacosException {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
agentCard.setName(AGENT_NAME);
|
||||||
|
agentCard.setVersion(AGENT_VERSION);
|
||||||
|
|
||||||
|
AgentCardUpdateForm form = new AgentCardUpdateForm();
|
||||||
|
form.setNamespaceId(NAMESPACE_ID);
|
||||||
|
form.setRegistrationType(REGISTRATION_TYPE);
|
||||||
|
form.setSetAsLatest(true);
|
||||||
|
|
||||||
|
doNothing().when(a2aServerOperationService)
|
||||||
|
.updateAgentCard(eq(agentCard), eq(NAMESPACE_ID), eq(REGISTRATION_TYPE), eq(true));
|
||||||
|
|
||||||
|
a2aInnerHandler.updateAgentCard(agentCard, form);
|
||||||
|
|
||||||
|
verify(a2aServerOperationService).updateAgentCard(eq(agentCard), eq(NAMESPACE_ID), eq(REGISTRATION_TYPE),
|
||||||
|
eq(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listAgents() throws NacosException {
|
||||||
|
AgentListForm agentListForm = new AgentListForm();
|
||||||
|
agentListForm.setNamespaceId(NAMESPACE_ID);
|
||||||
|
agentListForm.setAgentName(AGENT_NAME);
|
||||||
|
agentListForm.setSearch(SEARCH_TYPE);
|
||||||
|
|
||||||
|
PageForm pageForm = new PageForm();
|
||||||
|
pageForm.setPageNo(PAGE_NO);
|
||||||
|
pageForm.setPageSize(PAGE_SIZE);
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> expectedPage = new Page<>();
|
||||||
|
List<AgentCardVersionInfo> items = new ArrayList<>();
|
||||||
|
AgentCardVersionInfo info = new AgentCardVersionInfo();
|
||||||
|
info.setName(AGENT_NAME);
|
||||||
|
items.add(info);
|
||||||
|
expectedPage.setPageItems(items);
|
||||||
|
expectedPage.setPageNumber(PAGE_NO);
|
||||||
|
expectedPage.setPagesAvailable(1);
|
||||||
|
expectedPage.setTotalCount(1);
|
||||||
|
|
||||||
|
when(a2aServerOperationService.listAgents(eq(NAMESPACE_ID), eq(AGENT_NAME), eq(SEARCH_TYPE), eq(PAGE_NO),
|
||||||
|
eq(PAGE_SIZE))).thenReturn(expectedPage);
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> actualPage = a2aInnerHandler.listAgents(agentListForm, pageForm);
|
||||||
|
|
||||||
|
assertEquals(expectedPage, actualPage);
|
||||||
|
verify(a2aServerOperationService).listAgents(eq(NAMESPACE_ID), eq(AGENT_NAME), eq(SEARCH_TYPE), eq(PAGE_NO),
|
||||||
|
eq(PAGE_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listAgentVersions() throws NacosException {
|
||||||
|
List<AgentVersionDetail> expectedVersions = new ArrayList<>();
|
||||||
|
AgentVersionDetail version = new AgentVersionDetail();
|
||||||
|
version.setVersion(AGENT_VERSION);
|
||||||
|
expectedVersions.add(version);
|
||||||
|
|
||||||
|
when(a2aServerOperationService.listAgentVersions(eq(NAMESPACE_ID), eq(AGENT_NAME))).thenReturn(
|
||||||
|
expectedVersions);
|
||||||
|
|
||||||
|
List<AgentVersionDetail> actualVersions = a2aInnerHandler.listAgentVersions(NAMESPACE_ID, AGENT_NAME);
|
||||||
|
|
||||||
|
assertEquals(expectedVersions, actualVersions);
|
||||||
|
verify(a2aServerOperationService).listAgentVersions(eq(NAMESPACE_ID), eq(AGENT_NAME));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.nacos.console.handler.impl.noop.ai;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCard;
|
||||||
|
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||||
|
import com.alibaba.nacos.core.model.form.PageForm;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for A2aNoopHandler.
|
||||||
|
*
|
||||||
|
* @author nacos
|
||||||
|
*/
|
||||||
|
public class A2aNoopHandlerTest {
|
||||||
|
|
||||||
|
private static final String A2A_NOT_ENABLED_MESSAGE = "Nacos AI A2A module and API required both `naming` and `config` module.";
|
||||||
|
|
||||||
|
private A2aNoopHandler a2aNoopHandler;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
a2aNoopHandler = new A2aNoopHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerAgent() {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
AgentCardForm form = new AgentCardForm();
|
||||||
|
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aNoopHandler.registerAgent(agentCard, form),
|
||||||
|
A2A_NOT_ENABLED_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getAgentCardWithVersions() {
|
||||||
|
AgentForm form = new AgentForm();
|
||||||
|
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aNoopHandler.getAgentCardWithVersions(form),
|
||||||
|
A2A_NOT_ENABLED_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deleteAgent() {
|
||||||
|
AgentForm form = new AgentForm();
|
||||||
|
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aNoopHandler.deleteAgent(form),
|
||||||
|
A2A_NOT_ENABLED_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateAgentCard() {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
AgentCardUpdateForm form = new AgentCardUpdateForm();
|
||||||
|
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aNoopHandler.updateAgentCard(agentCard, form),
|
||||||
|
A2A_NOT_ENABLED_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listAgents() {
|
||||||
|
AgentListForm agentListForm = new AgentListForm();
|
||||||
|
PageForm pageForm = new PageForm();
|
||||||
|
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aNoopHandler.listAgents(agentListForm, pageForm),
|
||||||
|
A2A_NOT_ENABLED_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listAgentVersions() {
|
||||||
|
assertThrows(NacosApiException.class, () -> a2aNoopHandler.listAgentVersions("namespace", "agentName"),
|
||||||
|
A2A_NOT_ENABLED_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.nacos.console.handler.impl.remote.ai;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.ai.constant.Constants;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCard;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;
|
||||||
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
|
import com.alibaba.nacos.api.model.Page;
|
||||||
|
import com.alibaba.nacos.console.handler.impl.remote.AbstractRemoteHandlerTest;
|
||||||
|
import com.alibaba.nacos.core.model.form.PageForm;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for A2aRemoteHandler.
|
||||||
|
*
|
||||||
|
* @author nacos
|
||||||
|
*/
|
||||||
|
public class A2aRemoteHandlerTest extends AbstractRemoteHandlerTest {
|
||||||
|
|
||||||
|
private static final String NAMESPACE_ID = "test-namespace";
|
||||||
|
|
||||||
|
private static final String AGENT_NAME = "test-agent";
|
||||||
|
|
||||||
|
private static final String REGISTRATION_TYPE = "service";
|
||||||
|
|
||||||
|
private static final String SEARCH_TYPE_BLUR = Constants.MCP_LIST_SEARCH_BLUR;
|
||||||
|
|
||||||
|
private static final String SEARCH_TYPE_ACCURATE = "accurate";
|
||||||
|
|
||||||
|
private static final int PAGE_NO = 1;
|
||||||
|
|
||||||
|
private static final int PAGE_SIZE = 10;
|
||||||
|
|
||||||
|
private A2aRemoteHandler a2aRemoteHandler;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
super.setUpWithAi();
|
||||||
|
a2aRemoteHandler = new A2aRemoteHandler(clientHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerAgent() throws NacosException {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
agentCard.setName(AGENT_NAME);
|
||||||
|
|
||||||
|
AgentCardForm form = new AgentCardForm();
|
||||||
|
form.setNamespaceId(NAMESPACE_ID);
|
||||||
|
form.setRegistrationType(REGISTRATION_TYPE);
|
||||||
|
|
||||||
|
when(aiMaintainerService.registerAgent(eq(agentCard), eq(NAMESPACE_ID), eq(REGISTRATION_TYPE))).thenReturn(true);
|
||||||
|
a2aRemoteHandler.registerAgent(agentCard, form);
|
||||||
|
verify(aiMaintainerService).registerAgent(eq(agentCard), eq(NAMESPACE_ID), eq(REGISTRATION_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getAgentCardWithVersions() throws NacosException {
|
||||||
|
AgentForm form = new AgentForm();
|
||||||
|
form.setAgentName(AGENT_NAME);
|
||||||
|
form.setNamespaceId(NAMESPACE_ID);
|
||||||
|
form.setRegistrationType(REGISTRATION_TYPE);
|
||||||
|
|
||||||
|
AgentCardDetailInfo expectedDetailInfo = new AgentCardDetailInfo();
|
||||||
|
expectedDetailInfo.setName(AGENT_NAME);
|
||||||
|
|
||||||
|
when(aiMaintainerService.getAgentCard(eq(AGENT_NAME), eq(NAMESPACE_ID), eq(REGISTRATION_TYPE))).thenReturn(
|
||||||
|
expectedDetailInfo);
|
||||||
|
|
||||||
|
AgentCardDetailInfo actualDetailInfo = a2aRemoteHandler.getAgentCardWithVersions(form);
|
||||||
|
|
||||||
|
assertEquals(expectedDetailInfo, actualDetailInfo);
|
||||||
|
verify(aiMaintainerService).getAgentCard(eq(AGENT_NAME), eq(NAMESPACE_ID), eq(REGISTRATION_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deleteAgent() throws NacosException {
|
||||||
|
AgentForm form = new AgentForm();
|
||||||
|
form.setAgentName(AGENT_NAME);
|
||||||
|
form.setNamespaceId(NAMESPACE_ID);
|
||||||
|
|
||||||
|
when(aiMaintainerService.deleteAgent(eq(AGENT_NAME), eq(NAMESPACE_ID))).thenReturn(true);
|
||||||
|
|
||||||
|
a2aRemoteHandler.deleteAgent(form);
|
||||||
|
|
||||||
|
verify(aiMaintainerService).deleteAgent(eq(AGENT_NAME), eq(NAMESPACE_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateAgentCard() throws NacosException {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
agentCard.setName(AGENT_NAME);
|
||||||
|
|
||||||
|
AgentCardUpdateForm form = new AgentCardUpdateForm();
|
||||||
|
form.setNamespaceId(NAMESPACE_ID);
|
||||||
|
form.setSetAsLatest(true);
|
||||||
|
form.setRegistrationType(REGISTRATION_TYPE);
|
||||||
|
|
||||||
|
when(aiMaintainerService.updateAgentCard(eq(agentCard), eq(NAMESPACE_ID), eq(true),
|
||||||
|
eq(REGISTRATION_TYPE))).thenReturn(true);
|
||||||
|
|
||||||
|
a2aRemoteHandler.updateAgentCard(agentCard, form);
|
||||||
|
|
||||||
|
verify(aiMaintainerService).updateAgentCard(eq(agentCard), eq(NAMESPACE_ID), eq(true), eq(REGISTRATION_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listAgentsWithBlurSearch() throws NacosException {
|
||||||
|
AgentListForm agentListForm = new AgentListForm();
|
||||||
|
agentListForm.setNamespaceId(NAMESPACE_ID);
|
||||||
|
agentListForm.setAgentName(AGENT_NAME);
|
||||||
|
agentListForm.setSearch(SEARCH_TYPE_BLUR);
|
||||||
|
|
||||||
|
PageForm pageForm = new PageForm();
|
||||||
|
pageForm.setPageNo(PAGE_NO);
|
||||||
|
pageForm.setPageSize(PAGE_SIZE);
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> expectedPage = new Page<>();
|
||||||
|
|
||||||
|
when(aiMaintainerService.searchAgentCardsByName(eq(NAMESPACE_ID), eq(AGENT_NAME), eq(PAGE_NO),
|
||||||
|
eq(PAGE_SIZE))).thenReturn(expectedPage);
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> actualPage = a2aRemoteHandler.listAgents(agentListForm, pageForm);
|
||||||
|
|
||||||
|
assertEquals(expectedPage, actualPage);
|
||||||
|
verify(aiMaintainerService).searchAgentCardsByName(eq(NAMESPACE_ID), eq(AGENT_NAME), eq(PAGE_NO),
|
||||||
|
eq(PAGE_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listAgentsWithAccurateSearch() throws NacosException {
|
||||||
|
AgentListForm agentListForm = new AgentListForm();
|
||||||
|
agentListForm.setNamespaceId(NAMESPACE_ID);
|
||||||
|
agentListForm.setAgentName(AGENT_NAME);
|
||||||
|
agentListForm.setSearch(SEARCH_TYPE_ACCURATE);
|
||||||
|
|
||||||
|
PageForm pageForm = new PageForm();
|
||||||
|
pageForm.setPageNo(PAGE_NO);
|
||||||
|
pageForm.setPageSize(PAGE_SIZE);
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> expectedPage = new Page<>();
|
||||||
|
|
||||||
|
when(aiMaintainerService.listAgentCards(eq(NAMESPACE_ID), eq(AGENT_NAME), eq(PAGE_NO),
|
||||||
|
eq(PAGE_SIZE))).thenReturn(expectedPage);
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> actualPage = a2aRemoteHandler.listAgents(agentListForm, pageForm);
|
||||||
|
|
||||||
|
assertEquals(expectedPage, actualPage);
|
||||||
|
verify(aiMaintainerService).listAgentCards(eq(NAMESPACE_ID), eq(AGENT_NAME), eq(PAGE_NO), eq(PAGE_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listAgentVersions() throws NacosException {
|
||||||
|
List<AgentVersionDetail> expectedVersions = new ArrayList<>();
|
||||||
|
AgentVersionDetail version = new AgentVersionDetail();
|
||||||
|
version.setVersion("1.0.0");
|
||||||
|
expectedVersions.add(version);
|
||||||
|
|
||||||
|
when(aiMaintainerService.listAllVersionOfAgent(eq(AGENT_NAME), eq(NAMESPACE_ID))).thenReturn(expectedVersions);
|
||||||
|
|
||||||
|
List<AgentVersionDetail> actualVersions = a2aRemoteHandler.listAgentVersions(NAMESPACE_ID, AGENT_NAME);
|
||||||
|
|
||||||
|
assertEquals(expectedVersions, actualVersions);
|
||||||
|
verify(aiMaintainerService).listAllVersionOfAgent(eq(AGENT_NAME), eq(NAMESPACE_ID));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,192 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.nacos.console.proxy.ai;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentForm;
|
||||||
|
import com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCard;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;
|
||||||
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
|
import com.alibaba.nacos.api.model.Page;
|
||||||
|
import com.alibaba.nacos.console.handler.ai.A2aHandler;
|
||||||
|
import com.alibaba.nacos.core.model.form.PageForm;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.Mockito.doNothing;
|
||||||
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for A2aProxy.
|
||||||
|
*
|
||||||
|
* @author nacos
|
||||||
|
*/
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
public class A2aProxyTest {
|
||||||
|
|
||||||
|
private static final String NAMESPACE_ID = "test-namespace";
|
||||||
|
|
||||||
|
private static final String AGENT_NAME = "test-agent";
|
||||||
|
|
||||||
|
private static final String AGENT_VERSION = "1.0.0";
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private A2aHandler a2aHandler;
|
||||||
|
|
||||||
|
private A2aProxy a2aProxy;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp() {
|
||||||
|
a2aProxy = new A2aProxy(a2aHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegisterAgent() throws NacosException {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
agentCard.setName(AGENT_NAME);
|
||||||
|
AgentCardForm agentCardForm = new AgentCardForm();
|
||||||
|
|
||||||
|
doNothing().when(a2aHandler).registerAgent(agentCard, agentCardForm);
|
||||||
|
|
||||||
|
a2aProxy.registerAgent(agentCard, agentCardForm);
|
||||||
|
|
||||||
|
verify(a2aHandler, times(1)).registerAgent(agentCard, agentCardForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegisterAgentThrowsException() throws NacosException {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
agentCard.setName(AGENT_NAME);
|
||||||
|
AgentCardForm agentCardForm = new AgentCardForm();
|
||||||
|
NacosException expectedException = new NacosException(NacosException.INVALID_PARAM, "Invalid agent card");
|
||||||
|
|
||||||
|
doThrow(expectedException).when(a2aHandler).registerAgent(agentCard, agentCardForm);
|
||||||
|
|
||||||
|
NacosException actualException = assertThrows(NacosException.class,
|
||||||
|
() -> a2aProxy.registerAgent(agentCard, agentCardForm));
|
||||||
|
|
||||||
|
assertEquals(expectedException.getErrCode(), actualException.getErrCode());
|
||||||
|
assertEquals(expectedException.getMessage(), actualException.getMessage());
|
||||||
|
verify(a2aHandler, times(1)).registerAgent(agentCard, agentCardForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAgentCard() throws NacosException {
|
||||||
|
AgentForm form = new AgentForm();
|
||||||
|
form.setNamespaceId(NAMESPACE_ID);
|
||||||
|
form.setAgentName(AGENT_NAME);
|
||||||
|
|
||||||
|
AgentCardDetailInfo expectedDetailInfo = new AgentCardDetailInfo();
|
||||||
|
expectedDetailInfo.setName(AGENT_NAME);
|
||||||
|
|
||||||
|
when(a2aHandler.getAgentCardWithVersions(form)).thenReturn(expectedDetailInfo);
|
||||||
|
|
||||||
|
AgentCardDetailInfo actualDetailInfo = a2aProxy.getAgentCard(form);
|
||||||
|
|
||||||
|
assertNotNull(actualDetailInfo);
|
||||||
|
assertEquals(expectedDetailInfo, actualDetailInfo);
|
||||||
|
verify(a2aHandler, times(1)).getAgentCardWithVersions(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteAgent() throws NacosException {
|
||||||
|
AgentForm form = new AgentForm();
|
||||||
|
form.setNamespaceId(NAMESPACE_ID);
|
||||||
|
form.setAgentName(AGENT_NAME);
|
||||||
|
|
||||||
|
doNothing().when(a2aHandler).deleteAgent(form);
|
||||||
|
|
||||||
|
a2aProxy.deleteAgent(form);
|
||||||
|
|
||||||
|
verify(a2aHandler, times(1)).deleteAgent(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateAgentCard() throws NacosException {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
agentCard.setName(AGENT_NAME);
|
||||||
|
AgentCardUpdateForm form = new AgentCardUpdateForm();
|
||||||
|
form.setVersion(AGENT_VERSION);
|
||||||
|
|
||||||
|
doNothing().when(a2aHandler).updateAgentCard(agentCard, form);
|
||||||
|
|
||||||
|
a2aProxy.updateAgentCard(agentCard, form);
|
||||||
|
|
||||||
|
verify(a2aHandler, times(1)).updateAgentCard(agentCard, form);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testListAgents() throws NacosException {
|
||||||
|
AgentListForm agentListForm = new AgentListForm();
|
||||||
|
agentListForm.setNamespaceId(NAMESPACE_ID);
|
||||||
|
agentListForm.setAgentName(AGENT_NAME);
|
||||||
|
|
||||||
|
PageForm pageForm = new PageForm();
|
||||||
|
pageForm.setPageNo(1);
|
||||||
|
pageForm.setPageSize(10);
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> expectedPage = new Page<>();
|
||||||
|
List<AgentCardVersionInfo> items = new ArrayList<>();
|
||||||
|
AgentCardVersionInfo info = new AgentCardVersionInfo();
|
||||||
|
info.setName(AGENT_NAME);
|
||||||
|
items.add(info);
|
||||||
|
expectedPage.setPageItems(items);
|
||||||
|
expectedPage.setPageNumber(1);
|
||||||
|
expectedPage.setPagesAvailable(1);
|
||||||
|
expectedPage.setTotalCount(1);
|
||||||
|
|
||||||
|
when(a2aHandler.listAgents(agentListForm, pageForm)).thenReturn(expectedPage);
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> actualPage = a2aProxy.listAgents(agentListForm, pageForm);
|
||||||
|
|
||||||
|
assertNotNull(actualPage);
|
||||||
|
assertEquals(expectedPage, actualPage);
|
||||||
|
verify(a2aHandler, times(1)).listAgents(agentListForm, pageForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testListAgentVersions() throws NacosException {
|
||||||
|
List<AgentVersionDetail> expectedVersions = new ArrayList<>();
|
||||||
|
AgentVersionDetail version = new AgentVersionDetail();
|
||||||
|
version.setVersion(AGENT_VERSION);
|
||||||
|
expectedVersions.add(version);
|
||||||
|
|
||||||
|
when(a2aHandler.listAgentVersions(NAMESPACE_ID, AGENT_NAME)).thenReturn(expectedVersions);
|
||||||
|
|
||||||
|
List<AgentVersionDetail> actualVersions = a2aProxy.listAgentVersions(NAMESPACE_ID, AGENT_NAME);
|
||||||
|
|
||||||
|
assertNotNull(actualVersions);
|
||||||
|
assertEquals(expectedVersions, actualVersions);
|
||||||
|
verify(a2aHandler, times(1)).listAgentVersions(NAMESPACE_ID, AGENT_NAME);
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,10 @@ package com.alibaba.nacos.maintainer.client.ai;
|
||||||
|
|
||||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||||
import com.alibaba.nacos.api.ai.constant.AiConstants;
|
import com.alibaba.nacos.api.ai.constant.AiConstants;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCard;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;
|
||||||
|
import com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;
|
||||||
import com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;
|
import com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;
|
||||||
import com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;
|
import com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;
|
||||||
import com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;
|
import com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;
|
||||||
|
@ -39,17 +43,24 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for NacosAiMaintainerServiceImplTest.
|
||||||
|
*
|
||||||
|
* @author nacos
|
||||||
|
*/
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class NacosAiMaintainerServiceImplTest {
|
public class NacosAiMaintainerServiceImplTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
ClientHttpProxy clientHttpProxy;
|
ClientHttpProxy clientHttpProxy;
|
||||||
|
@ -230,4 +241,127 @@ class NacosAiMaintainerServiceImplTest {
|
||||||
when(clientHttpProxy.executeSyncHttpRequest(any(HttpRequest.class))).thenReturn(mockRestResult);
|
when(clientHttpProxy.executeSyncHttpRequest(any(HttpRequest.class))).thenReturn(mockRestResult);
|
||||||
assertTrue(aiMaintainerService.deleteMcpServer("test"));
|
assertTrue(aiMaintainerService.deleteMcpServer("test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerAgent() throws NacosException {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
agentCard.setName("testAgent");
|
||||||
|
agentCard.setVersion("1.0.0");
|
||||||
|
|
||||||
|
final HttpRestResult<String> mockRestResult = new HttpRestResult<>();
|
||||||
|
mockRestResult.setData(JacksonUtils.toJson(Result.success("ok")));
|
||||||
|
when(clientHttpProxy.executeSyncHttpRequest(any(HttpRequest.class))).thenReturn(mockRestResult);
|
||||||
|
|
||||||
|
assertTrue(aiMaintainerService.registerAgent(agentCard, "public", "url"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getAgentCard() throws NacosException {
|
||||||
|
AgentCardDetailInfo expected = new AgentCardDetailInfo();
|
||||||
|
expected.setName("testAgent");
|
||||||
|
expected.setVersion("1.0.0");
|
||||||
|
expected.setRegistrationType("url");
|
||||||
|
expected.setLatestVersion(true);
|
||||||
|
|
||||||
|
final HttpRestResult<String> mockRestResult = new HttpRestResult<>();
|
||||||
|
mockRestResult.setData(JacksonUtils.toJson(Result.success(expected)));
|
||||||
|
when(clientHttpProxy.executeSyncHttpRequest(any(HttpRequest.class))).thenReturn(mockRestResult);
|
||||||
|
|
||||||
|
AgentCardDetailInfo actual = aiMaintainerService.getAgentCard("testAgent", "public", "url");
|
||||||
|
assertNotNull(actual);
|
||||||
|
assertEquals("testAgent", actual.getName());
|
||||||
|
assertEquals("1.0.0", actual.getVersion());
|
||||||
|
assertEquals("url", actual.getRegistrationType());
|
||||||
|
assertTrue(actual.isLatestVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateAgentCard() throws NacosException {
|
||||||
|
AgentCard agentCard = new AgentCard();
|
||||||
|
agentCard.setName("testAgent");
|
||||||
|
agentCard.setVersion("1.0.0");
|
||||||
|
|
||||||
|
final HttpRestResult<String> mockRestResult = new HttpRestResult<>();
|
||||||
|
mockRestResult.setData(JacksonUtils.toJson(Result.success("ok")));
|
||||||
|
when(clientHttpProxy.executeSyncHttpRequest(any(HttpRequest.class))).thenReturn(mockRestResult);
|
||||||
|
|
||||||
|
assertTrue(aiMaintainerService.updateAgentCard(agentCard, "public", true, "url"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deleteAgent() throws NacosException {
|
||||||
|
final HttpRestResult<String> mockRestResult = new HttpRestResult<>();
|
||||||
|
mockRestResult.setData(JacksonUtils.toJson(Result.success("ok")));
|
||||||
|
when(clientHttpProxy.executeSyncHttpRequest(any(HttpRequest.class))).thenReturn(mockRestResult);
|
||||||
|
|
||||||
|
assertTrue(aiMaintainerService.deleteAgent("testAgent", "public", "1.0.0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listAllVersionOfAgent() throws NacosException {
|
||||||
|
AgentVersionDetail versionDetail = new AgentVersionDetail();
|
||||||
|
versionDetail.setVersion("1.0.0");
|
||||||
|
versionDetail.setCreatedAt("2024-01-01T00:00:00");
|
||||||
|
versionDetail.setUpdatedAt("2024-01-01T00:00:00");
|
||||||
|
versionDetail.setLatest(true);
|
||||||
|
|
||||||
|
List<AgentVersionDetail> expectedVersions = Collections.singletonList(versionDetail);
|
||||||
|
|
||||||
|
final HttpRestResult<String> mockRestResult = new HttpRestResult<>();
|
||||||
|
mockRestResult.setData(JacksonUtils.toJson(Result.success(expectedVersions)));
|
||||||
|
when(clientHttpProxy.executeSyncHttpRequest(any(HttpRequest.class))).thenReturn(mockRestResult);
|
||||||
|
|
||||||
|
List<AgentVersionDetail> actualVersions = aiMaintainerService.listAllVersionOfAgent("testAgent", "public");
|
||||||
|
assertNotNull(actualVersions);
|
||||||
|
assertEquals(1, actualVersions.size());
|
||||||
|
assertEquals("1.0.0", actualVersions.get(0).getVersion());
|
||||||
|
assertEquals("2024-01-01T00:00:00", actualVersions.get(0).getCreatedAt());
|
||||||
|
assertTrue(actualVersions.get(0).isLatest());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void searchAgentCardsByName() throws NacosException {
|
||||||
|
AgentCardVersionInfo agentCardVersionInfo = new AgentCardVersionInfo();
|
||||||
|
agentCardVersionInfo.setName("testAgent");
|
||||||
|
agentCardVersionInfo.setLatestPublishedVersion("1.0.0");
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> page = new Page<>();
|
||||||
|
page.setPagesAvailable(1);
|
||||||
|
page.setTotalCount(1);
|
||||||
|
page.setPageNumber(1);
|
||||||
|
page.setPageItems(Collections.singletonList(agentCardVersionInfo));
|
||||||
|
|
||||||
|
final HttpRestResult<String> mockRestResult = new HttpRestResult<>();
|
||||||
|
mockRestResult.setData(JacksonUtils.toJson(Result.success(page)));
|
||||||
|
when(clientHttpProxy.executeSyncHttpRequest(any(HttpRequest.class))).thenReturn(mockRestResult);
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> actual = aiMaintainerService.searchAgentCardsByName("public", "test", 1, 10);
|
||||||
|
assertNotNull(actual);
|
||||||
|
assertEquals(1, actual.getTotalCount());
|
||||||
|
assertEquals(1, actual.getPageItems().size());
|
||||||
|
assertEquals("testAgent", actual.getPageItems().get(0).getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listAgentCards() throws NacosException {
|
||||||
|
AgentCardVersionInfo agentCardVersionInfo = new AgentCardVersionInfo();
|
||||||
|
agentCardVersionInfo.setName("testAgent");
|
||||||
|
agentCardVersionInfo.setLatestPublishedVersion("1.0.0");
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> page = new Page<>();
|
||||||
|
page.setPagesAvailable(1);
|
||||||
|
page.setTotalCount(1);
|
||||||
|
page.setPageNumber(1);
|
||||||
|
page.setPageItems(Collections.singletonList(agentCardVersionInfo));
|
||||||
|
|
||||||
|
final HttpRestResult<String> mockRestResult = new HttpRestResult<>();
|
||||||
|
mockRestResult.setData(JacksonUtils.toJson(Result.success(page)));
|
||||||
|
when(clientHttpProxy.executeSyncHttpRequest(any(HttpRequest.class))).thenReturn(mockRestResult);
|
||||||
|
|
||||||
|
Page<AgentCardVersionInfo> actual = aiMaintainerService.listAgentCards("public", "testAgent", 1, 10);
|
||||||
|
assertNotNull(actual);
|
||||||
|
assertEquals(1, actual.getTotalCount());
|
||||||
|
assertEquals(1, actual.getPageItems().size());
|
||||||
|
assertEquals("testAgent", actual.getPageItems().get(0).getName());
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue