This is an automated email from the ASF dual-hosted git repository.
liuhaopeng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/bigtop-manager.git
The following commit(s) were added to refs/heads/main by this push:
new e10701d7 BIGTOP-4344: Add ut cases for tools classes in server module
(#164)
e10701d7 is described below
commit e10701d745a1805923d509554186737abdea9cd8
Author: xianrenzw <[email protected]>
AuthorDate: Wed Feb 5 01:00:34 2025 +0800
BIGTOP-4344: Add ut cases for tools classes in server module (#164)
---
.../tools/functions/ClusterFunctionsTest.java | 180 +++++++++++++++++++++
.../server/tools/functions/HostFunctionsTest.java | 155 ++++++++++++++++++
.../server/tools/functions/StackFunctionsTest.java | 173 ++++++++++++++++++++
.../tools/provider/AIServiceToolsProviderTest.java | 62 +++++++
4 files changed, 570 insertions(+)
diff --git
a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/functions/ClusterFunctionsTest.java
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/functions/ClusterFunctionsTest.java
new file mode 100644
index 00000000..6a522da7
--- /dev/null
+++
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/functions/ClusterFunctionsTest.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * https://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 org.apache.bigtop.manager.server.tools.functions;
+
+import org.apache.bigtop.manager.server.model.vo.ClusterVO;
+import org.apache.bigtop.manager.server.service.ClusterService;
+
+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 dev.langchain4j.agent.tool.ToolExecutionRequest;
+import dev.langchain4j.agent.tool.ToolSpecification;
+import dev.langchain4j.service.tool.ToolExecutor;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class ClusterFunctionsTest {
+
+ @Mock
+ private ClusterService clusterService;
+
+ @InjectMocks
+ private ClusterFunctions clusterFunctions;
+
+ private ClusterVO testCluster;
+
+ @BeforeEach
+ void setUp() {
+ testCluster = new ClusterVO();
+ testCluster.setId(1L);
+ testCluster.setName("test-cluster");
+ }
+
+ @Test
+ void testListCluster() {
+ // Mock clusterService response
+
when(clusterService.list()).thenReturn(Collections.singletonList(testCluster));
+
+ // Get the tool specification and executor
+ Map<ToolSpecification, ToolExecutor> tools =
clusterFunctions.listCluster();
+ assertEquals(1, tools.size());
+
+ ToolSpecification spec = tools.keySet().iterator().next();
+ ToolExecutor executor = tools.get(spec);
+
+ // Execute the tool
+ String result =
executor.execute(ToolExecutionRequest.builder().build(), "memoryId");
+
+ // Verify results
+ assertTrue(result.contains("test-cluster"));
+ verify(clusterService, times(1)).list();
+ }
+
+ @Test
+ void testGetClusterById() {
+ // Mock clusterService response
+ when(clusterService.get(1L)).thenReturn(testCluster);
+
+ // Get the tool specification and executor
+ Map<ToolSpecification, ToolExecutor> tools =
clusterFunctions.getClusterById();
+ assertEquals(1, tools.size());
+
+ ToolSpecification spec = tools.keySet().iterator().next();
+ ToolExecutor executor = tools.get(spec);
+
+ // Build request with arguments
+ String arguments = "{\"clusterId\": 1}";
+ ToolExecutionRequest request =
+ ToolExecutionRequest.builder().arguments(arguments).build();
+
+ // Execute the tool
+ String result = executor.execute(request, "memoryId");
+
+ // Verify results
+ assertTrue(result.contains("test-cluster"));
+ verify(clusterService, times(1)).get(1L);
+ }
+
+ @Test
+ void testGetClusterByIdWhenNotExists() {
+ // Mock clusterService response
+ when(clusterService.get(999L)).thenReturn(null);
+
+ // Get the tool specification and executor
+ Map<ToolSpecification, ToolExecutor> tools =
clusterFunctions.getClusterById();
+ ToolExecutor executor = tools.values().iterator().next();
+
+ // Build request with arguments
+ String arguments = "{\"clusterId\": 999}";
+ ToolExecutionRequest request =
+ ToolExecutionRequest.builder().arguments(arguments).build();
+
+ // Execute the tool
+ String result = executor.execute(request, "memoryId");
+
+ // Verify results
+ assertEquals("Cluster not found", result);
+ }
+
+ @Test
+ void testGetClusterByName() {
+ // Mock clusterService response
+
when(clusterService.list()).thenReturn(Collections.singletonList(testCluster));
+
+ // Get the tool specification and executor
+ Map<ToolSpecification, ToolExecutor> tools =
clusterFunctions.getClusterByName();
+ ToolExecutor executor = tools.values().iterator().next();
+
+ // Build request with arguments
+ String arguments = "{\"clusterName\": \"test-cluster\"}";
+ ToolExecutionRequest request =
+ ToolExecutionRequest.builder().arguments(arguments).build();
+
+ // Execute the tool
+ String result = executor.execute(request, "memoryId");
+
+ // Verify results
+ assertTrue(result.contains("test-cluster"));
+ verify(clusterService, times(1)).list();
+ }
+
+ @Test
+ void testGetClusterByNameWhenNotExists() {
+ // Mock clusterService response
+
when(clusterService.list()).thenReturn(Collections.singletonList(testCluster));
+
+ // Get the tool specification and executor
+ Map<ToolSpecification, ToolExecutor> tools =
clusterFunctions.getClusterByName();
+ ToolExecutor executor = tools.values().iterator().next();
+
+ // Build request with arguments
+ String arguments = "{\"clusterName\": \"non-existent\"}";
+ ToolExecutionRequest request =
+ ToolExecutionRequest.builder().arguments(arguments).build();
+
+ // Execute the tool
+ String result = executor.execute(request, "memoryId");
+
+ // Verify results
+ assertEquals("Cluster not found", result);
+ }
+
+ @Test
+ void testGetAllFunctions() {
+ Map<ToolSpecification, ToolExecutor> functions =
clusterFunctions.getAllFunctions();
+ assertEquals(3, functions.size());
+
+ List<String> expectedToolNames = List.of("listCluster",
"getClusterById", "getClusterByName");
+
assertTrue(functions.keySet().stream().map(ToolSpecification::name).allMatch(expectedToolNames::contains));
+ }
+}
diff --git
a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/functions/HostFunctionsTest.java
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/functions/HostFunctionsTest.java
new file mode 100644
index 00000000..267a2ccf
--- /dev/null
+++
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/functions/HostFunctionsTest.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * https://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 org.apache.bigtop.manager.server.tools.functions;
+
+import org.apache.bigtop.manager.dao.query.HostQuery;
+import org.apache.bigtop.manager.server.model.vo.HostVO;
+import org.apache.bigtop.manager.server.model.vo.PageVO;
+import org.apache.bigtop.manager.server.service.HostService;
+
+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 dev.langchain4j.agent.tool.ToolExecutionRequest;
+import dev.langchain4j.agent.tool.ToolSpecification;
+import dev.langchain4j.service.tool.ToolExecutor;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class HostFunctionsTest {
+
+ @Mock
+ private HostService hostService;
+
+ @InjectMocks
+ private HostFunctions hostFunctions;
+
+ private HostVO testHost;
+ private PageVO<HostVO> testPage;
+
+ @BeforeEach
+ void setUp() {
+ testHost = new HostVO();
+ testHost.setId(1L);
+ testHost.setHostname("test-host");
+
+ testPage = new PageVO<>();
+ testPage.setContent(List.of(testHost));
+ testPage.setTotal(1L);
+ }
+
+ @Test
+ void testGetHostByIdToolSpecification() {
+ Map<ToolSpecification, ToolExecutor> tools =
hostFunctions.getHostById();
+ assertEquals(1, tools.size());
+
+ ToolSpecification spec = tools.keySet().iterator().next();
+ Map<String, Map<String, Object>> params =
spec.parameters().properties();
+
+ assertEquals(1, params.size());
+ assertTrue(params.containsKey("hostId"));
+ assertEquals("number", params.get("hostId").get("type"));
+ assertEquals("host id", params.get("hostId").get("description"));
+ }
+
+ @Test
+ void testGetHostByIdExecutorFound() throws Exception {
+ when(hostService.get(1L)).thenReturn(testHost);
+
+ Map<ToolSpecification, ToolExecutor> tools =
hostFunctions.getHostById();
+ ToolExecutor executor = tools.values().iterator().next();
+
+ String arguments = "{\"hostId\": 1}";
+ String result = executor.execute(
+ ToolExecutionRequest.builder().arguments(arguments).build(),
null);
+
+ // Use system-independent newline character regex
+ String expectedPattern = ".*\"hostname\"\\s*:\\s*\"test-host\".*";
+ assertTrue(
+ result.replaceAll("\\R",
System.lineSeparator()).matches("(?s)" + expectedPattern),
+ "Hostname should match with any line separators");
+ }
+
+ @Test
+ void testGetHostByIdExecutorNotFound() {
+ when(hostService.get(anyLong())).thenReturn(null);
+
+ Map<ToolSpecification, ToolExecutor> tools =
hostFunctions.getHostById();
+ ToolExecutor executor = tools.values().iterator().next();
+
+ String arguments = "{\"hostId\": 999}";
+ String result = executor.execute(
+ ToolExecutionRequest.builder().arguments(arguments).build(),
null);
+
+ assertEquals("Host not found", result);
+ }
+
+ @Test
+ void testGetHostByNameToolSpecification() {
+ Map<ToolSpecification, ToolExecutor> tools =
hostFunctions.getHostByName();
+ assertEquals(1, tools.size());
+
+ ToolSpecification spec = tools.keySet().iterator().next();
+ assertEquals("getHostByName", spec.name());
+ assertEquals("Get host information based on cluster name",
spec.description());
+ Map<String, Map<String, Object>> params =
spec.parameters().properties();
+ assertEquals(1, params.size());
+ assertTrue(params.containsKey("hostName"));
+ assertEquals("string", params.get("hostName").get("type"));
+ }
+
+ @Test
+ void testGetHostByNameExecutor() {
+ HostQuery query = new HostQuery();
+ query.setHostname("test-host");
+ when(hostService.list(query)).thenReturn(testPage);
+
+ Map<ToolSpecification, ToolExecutor> tools =
hostFunctions.getHostByName();
+ ToolExecutor executor = tools.values().iterator().next();
+
+ String arguments = "{\"hostName\":\"test-host\"}";
+ String result = executor.execute(
+ ToolExecutionRequest.builder().arguments(arguments).build(),
null);
+
+ // System-independent matching pattern
+ String totalPattern = "(?s).*\"total\"\\s*:\\s*1.*";
+ String hostPattern = "(?s).*\"hostname\"\\s*:\\s*\"test-host\".*";
+ assertTrue(result.matches(totalPattern), "Should contain total=1");
+ assertTrue(result.matches(hostPattern), "Should contain
hostname=test-host");
+ }
+
+ @Test
+ void testGetAllFunctions() {
+ Map<ToolSpecification, ToolExecutor> functions =
hostFunctions.getAllFunctions();
+ assertEquals(2, functions.size());
+ assertTrue(functions.keySet().stream().anyMatch(s ->
s.name().equals("getHostById")));
+ assertTrue(functions.keySet().stream().anyMatch(s ->
s.name().equals("getHostByName")));
+ }
+}
diff --git
a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/functions/StackFunctionsTest.java
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/functions/StackFunctionsTest.java
new file mode 100644
index 00000000..481f04ce
--- /dev/null
+++
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/functions/StackFunctionsTest.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * https://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 org.apache.bigtop.manager.server.tools.functions;
+
+import org.apache.bigtop.manager.server.model.vo.AttrsVO;
+import org.apache.bigtop.manager.server.model.vo.PropertyVO;
+import org.apache.bigtop.manager.server.model.vo.ServiceConfigVO;
+import org.apache.bigtop.manager.server.model.vo.ServiceVO;
+import org.apache.bigtop.manager.server.model.vo.StackVO;
+import org.apache.bigtop.manager.server.service.StackService;
+
+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 dev.langchain4j.agent.tool.ToolExecutionRequest;
+import dev.langchain4j.agent.tool.ToolSpecification;
+import dev.langchain4j.service.tool.ToolExecutor;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class StackFunctionsTest {
+
+ @Mock
+ private StackService stackService;
+
+ @InjectMocks
+ private StackFunctions stackFunctions;
+
+ private StackVO testStack;
+
+ @BeforeEach
+ void setUp() {
+ // Initialize test data
+ testStack = new StackVO();
+ testStack.setStackName("test-stack");
+
+ ServiceVO testService = new ServiceVO();
+ testService.setName("test-service");
+
+ ServiceConfigVO config = new ServiceConfigVO();
+ PropertyVO normalProp = new PropertyVO();
+ normalProp.setName("normal");
+ normalProp.setValue("value");
+ PropertyVO contentProp = new PropertyVO();
+ contentProp.setName("content");
+ contentProp.setValue("secret");
+ PropertyVO longtextProp = new PropertyVO();
+ longtextProp.setName("longtext");
+ longtextProp.setValue("very long text");
+ AttrsVO attrs = new AttrsVO();
+ attrs.setType("longtext");
+ longtextProp.setAttrs(attrs);
+
+ config.setProperties(List.of(normalProp, contentProp, longtextProp));
+ testService.setConfigs(List.of(config));
+
+ testStack.setServices(List.of(testService));
+ }
+
+ @Test
+ void testListStackAndService() {
+ // Mock service layer return data
+ when(stackService.list()).thenReturn(List.of(testStack));
+
+ // Get tool
+ Map<ToolSpecification, ToolExecutor> tools =
stackFunctions.listStackAndService();
+ assertEquals(1, tools.size());
+
+ // Validate tool specification
+ ToolSpecification spec = tools.keySet().iterator().next();
+ assertEquals("listStackAndService", spec.name());
+ assertEquals("Retrieve the list of services in each stack",
spec.description());
+
+ // Execute tool
+ ToolExecutor executor = tools.values().iterator().next();
+ String result =
+
executor.execute(ToolExecutionRequest.builder().arguments("{}").build(), null);
+
+ // Validate result
+ String expectedJson =
+ """
+ {
+ "test-stack": ["test-service"]
+ }""";
+ assertEquals(expectedJson.replaceAll("\\s", ""),
result.replaceAll("\\s", ""));
+ }
+
+ @Test
+ void testGetServiceByNameFound() {
+ // Mock service layer return data
+ when(stackService.list()).thenReturn(List.of(testStack));
+
+ // Get tool
+ Map<ToolSpecification, ToolExecutor> tools =
stackFunctions.getServiceByName();
+ ToolExecutor executor = tools.values().iterator().next();
+
+ // Execute query
+ String arguments = "{\"serviceName\" : \"test-service\"}";
+ String result = executor.execute(
+ ToolExecutionRequest.builder().arguments(arguments).build(),
null);
+
+ // Validate result
+ assertAll(
+ () -> assertTrue(result.contains("\"name\" :
\"test-service\"")),
+ () -> assertTrue(result.contains("\"name\" : \"normal\"")),
+ () -> assertTrue(result.contains("\"name\" : \"content\"")),
+ () -> assertTrue(result.contains("\"name\" : \"longtext\"")));
+ }
+
+ @Test
+ void testGetServiceByNameNotFound() {
+ when(stackService.list()).thenReturn(List.of(testStack));
+
+ Map<ToolSpecification, ToolExecutor> tools =
stackFunctions.getServiceByName();
+ ToolExecutor executor = tools.values().iterator().next();
+
+ String arguments = "{\"serviceName\":\"non-existent\"}";
+ String result = executor.execute(
+ ToolExecutionRequest.builder().arguments(arguments).build(),
null);
+
+ assertEquals("Service not found", result);
+ }
+
+ @Test
+ void testGetServiceByNameToolSpecification() {
+ Map<ToolSpecification, ToolExecutor> tools =
stackFunctions.getServiceByName();
+ ToolSpecification spec = tools.keySet().iterator().next();
+ Map<String, Map<String, Object>> params =
spec.parameters().properties();
+ assertAll(
+ () -> assertEquals("getServiceByName", spec.name()),
+ () -> assertEquals("Get service information and configs based
on service name", spec.description()),
+ () -> assertEquals(1, params.size()),
+ () -> assertTrue(params.containsKey("serviceName")),
+ () -> assertEquals("string",
params.get("serviceName").get("type")),
+ () -> assertEquals(
+ "Lowercase service name",
params.get("serviceName").get("description")));
+ }
+
+ @Test
+ void testGetAllFunctions() {
+ Map<ToolSpecification, ToolExecutor> functions =
stackFunctions.getAllFunctions();
+ assertEquals(2, functions.size());
+ assertTrue(functions.keySet().stream().anyMatch(s ->
s.name().equals("listStackAndService")));
+ assertTrue(functions.keySet().stream().anyMatch(s ->
s.name().equals("getServiceByName")));
+ }
+}
diff --git
a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/provider/AIServiceToolsProviderTest.java
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/provider/AIServiceToolsProviderTest.java
new file mode 100644
index 00000000..475dfe3f
--- /dev/null
+++
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/tools/provider/AIServiceToolsProviderTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * https://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 org.apache.bigtop.manager.server.tools.provider;
+
+import org.apache.bigtop.manager.server.enums.ChatbotCommand;
+
+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 dev.langchain4j.service.tool.ToolProvider;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+@ExtendWith(MockitoExtension.class)
+public class AIServiceToolsProviderTest {
+
+ @Mock
+ private InfoToolsProvider infoToolsProvider;
+
+ @InjectMocks
+ private AIServiceToolsProvider aiServiceToolsProvider;
+
+ @Test
+ public void testGetToolsProvideWithInfoCommand() {
+ ToolProvider toolProvider =
aiServiceToolsProvider.getToolsProvide(ChatbotCommand.INFO);
+ assertNotNull(toolProvider);
+ assertEquals(infoToolsProvider, toolProvider);
+ }
+
+ @Test
+ public void testGetToolsProvideWithOtherCommand() {
+ ToolProvider toolProvider =
aiServiceToolsProvider.getToolsProvide(ChatbotCommand.HELP);
+ assertNull(toolProvider);
+ }
+
+ @Test
+ public void testGetToolsProvideWithNullCommand() {
+ ToolProvider toolProvider =
aiServiceToolsProvider.getToolsProvide(null);
+ assertNull(toolProvider);
+ }
+}