diff --git a/bigtop-manager-agent/src/main/java/org/apache/bigtop/manager/agent/service/CommandServiceGrpcImpl.java b/bigtop-manager-agent/src/main/java/org/apache/bigtop/manager/agent/service/CommandServiceGrpcImpl.java index 920e418b..6bff53ca 100644 --- a/bigtop-manager-agent/src/main/java/org/apache/bigtop/manager/agent/service/CommandServiceGrpcImpl.java +++ b/bigtop-manager-agent/src/main/java/org/apache/bigtop/manager/agent/service/CommandServiceGrpcImpl.java @@ -63,7 +63,7 @@ public void exec(CommandRequest request, StreamObserver responseOb } } - private void truncateLogFile(Long taskId) { + protected void truncateLogFile(Long taskId) { String filePath = ProjectPathUtils.getLogFilePath(taskId); File file = new File(filePath); if (file.exists()) { diff --git a/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/holder/SpringContextHolderTest.java b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/holder/SpringContextHolderTest.java new file mode 100644 index 00000000..4eb0e7d6 --- /dev/null +++ b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/holder/SpringContextHolderTest.java @@ -0,0 +1,78 @@ +/* + * 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.agent.holder; + +import org.apache.bigtop.manager.agent.executor.CommandExecutor; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.context.ApplicationContext; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +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; + +public class SpringContextHolderTest { + + @Mock + private ApplicationContext mockApplicationContext; + + @Mock + private CommandExecutor mockCommandExecutor; + + @BeforeEach + public void setUp() throws Exception { + MockitoAnnotations.openMocks(this); + + // Use reflection to set the static variable applicationContext + Field field = SpringContextHolder.class.getDeclaredField("applicationContext"); + field.setAccessible(true); + field.set(null, mockApplicationContext); + } + + @Test + public void testGetCommandExecutors() { + // Prepare test data + Map commandExecutorsMap = new HashMap<>(); + commandExecutorsMap.put("commandExecutor1", mockCommandExecutor); + when(mockApplicationContext.getBeansOfType(CommandExecutor.class)).thenReturn(commandExecutorsMap); + + // Execute the method under test + Map result = SpringContextHolder.getCommandExecutors(); + + // Validate the result + assertNotNull(result); + assertEquals(1, result.size()); + assertTrue(result.containsKey("commandExecutor1")); + assertSame(mockCommandExecutor, result.get("commandExecutor1")); + + // Verify method calls + verify(mockApplicationContext, times(1)).getBeansOfType(CommandExecutor.class); + } +} diff --git a/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/monitoring/AgentHostMonitoringTest.java b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/monitoring/AgentHostMonitoringTest.java new file mode 100644 index 00000000..8fcb8cbc --- /dev/null +++ b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/monitoring/AgentHostMonitoringTest.java @@ -0,0 +1,227 @@ +/* + * 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.agent.monitoring; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import io.micrometer.core.instrument.MultiGauge; +import oshi.SystemInfo; +import oshi.hardware.GlobalMemory; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.software.os.OperatingSystem; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class AgentHostMonitoringTest { + + @Mock + private SystemInfo systemInfo; + + @Mock + private HardwareAbstractionLayer hardwareAbstractionLayer; + + @Mock + private GlobalMemory globalMemory; + + @Mock + private MultiGauge diskMultiGauge; + + @Mock + private MultiGauge memMultiGauge; + + @Mock + private MultiGauge cpuMultiGauge; + + @Mock + private MultiGauge diskIOMultiGauge; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + when(systemInfo.getOperatingSystem()).thenReturn(mock(OperatingSystem.class)); + when(systemInfo.getHardware()).thenReturn(hardwareAbstractionLayer); + when(hardwareAbstractionLayer.getMemory()).thenReturn(globalMemory); + when(globalMemory.getAvailable()).thenReturn(100000L); + when(globalMemory.getTotal()).thenReturn(200000L); + } + + @Test + void testGetHostInfo() throws UnknownHostException { + JsonNode hostInfo = AgentHostMonitoring.getHostInfo(); + + // Check if the host information contains expected fields + assertTrue(hostInfo.has(AgentHostMonitoring.AGENT_BASE_INFO)); + assertTrue(hostInfo.has(AgentHostMonitoring.BOOT_TIME)); + assertTrue(hostInfo.has(AgentHostMonitoring.MEM_IDLE)); + assertTrue(hostInfo.has(AgentHostMonitoring.MEM_TOTAL)); + } + + @Test + void testGetDiskGauge() { + // Create a mock JsonNode object + JsonNode agentMonitoring = mock(JsonNode.class); + + // Create a mock agentHostInfo object and set its fields + ObjectNode agentHostInfo = mock(ObjectNode.class); + when(agentMonitoring.get(AgentHostMonitoring.AGENT_BASE_INFO)).thenReturn(agentHostInfo); + when(agentHostInfo.fieldNames()).thenReturn(Collections.emptyIterator()); + + // Create a mock disksBaseInfo object and set its fields + ArrayNode disksBaseInfo = mock(ArrayNode.class); + when(agentMonitoring.get(AgentHostMonitoring.DISKS_BASE_INFO)).thenReturn(disksBaseInfo); + + // Create a mock diskJsonNode object and set its fields + ObjectNode diskJsonNode = mock(ObjectNode.class); + when(disksBaseInfo.get(0)).thenReturn(diskJsonNode); + when(diskJsonNode.get(AgentHostMonitoring.DISK_NAME)).thenReturn(mock(JsonNode.class)); + when(diskJsonNode.get(AgentHostMonitoring.DISK_IDLE)).thenReturn(mock(JsonNode.class)); + when(diskJsonNode.get(AgentHostMonitoring.DISK_TOTAL)).thenReturn(mock(JsonNode.class)); + when(diskJsonNode.get(AgentHostMonitoring.DISK_NAME).asText()).thenReturn("disk1"); + when(diskJsonNode.get(AgentHostMonitoring.DISK_IDLE).asDouble()).thenReturn(0.9); + when(diskJsonNode.get(AgentHostMonitoring.DISK_TOTAL).asDouble()).thenReturn(100.0); + + // Call the getDiskGauge method + Map, Map, Double>> diskGauge = + AgentHostMonitoring.getDiskGauge(agentMonitoring); + + // Assert that the disk gauge data is populated correctly + assertNotNull(diskGauge); + assertFalse(diskGauge.isEmpty()); + } + + @Test + void testGetCPUGauge() { + ObjectMapper objectMapper = new ObjectMapper(); + ObjectNode agentMonitoring = objectMapper.createObjectNode(); + ObjectNode agentHostInfo = objectMapper.createObjectNode(); + + // Set AGENT_BASE_INFO fields + agentHostInfo.put("field1", "value1"); + agentHostInfo.put("field2", "value2"); + agentMonitoring.set(AgentHostMonitoring.AGENT_BASE_INFO, agentHostInfo); + + // Set CPU related fields + agentMonitoring + .put(AgentHostMonitoring.CPU_LOAD_AVG_MIN_1, 1.0) + .put(AgentHostMonitoring.CPU_LOAD_AVG_MIN_5, 5.0) + .put(AgentHostMonitoring.CPU_LOAD_AVG_MIN_15, 15.0) + .put(AgentHostMonitoring.CPU_USAGE, 10.0); + + Map, Map, Double>> cpuGauge = + AgentHostMonitoring.getCPUGauge(agentMonitoring); + + // Assert that the CPU gauge data is populated correctly + assertNotNull(cpuGauge); + assertFalse(cpuGauge.isEmpty()); + } + + @Test + void testGetMEMGauge() { + ObjectMapper objectMapper = new ObjectMapper(); + ObjectNode agentMonitoring = objectMapper.createObjectNode(); + ObjectNode agentHostInfo = objectMapper.createObjectNode(); + + // Set AGENT_BASE_INFO fields + agentHostInfo.put("field1", "value1"); + agentHostInfo.put("field2", "value2"); + agentMonitoring.set(AgentHostMonitoring.AGENT_BASE_INFO, agentHostInfo); + + // Set MEM related fields + agentMonitoring.put(AgentHostMonitoring.MEM_IDLE, 2000.0).put(AgentHostMonitoring.MEM_TOTAL, 4000.0); + + Map, Map, Double>> memGauge = + AgentHostMonitoring.getMEMGauge(agentMonitoring); + + // Assert that the MEM gauge data is populated correctly + assertNotNull(memGauge); + assertFalse(memGauge.isEmpty()); + } + + @Test + void testMultiGaugeUpdateData() { + // Create a mock Map object + Map, Map, Double>> diskGauge = new HashMap<>(); + Map, Double> innerMap = new HashMap<>(); + innerMap.put(new ArrayList<>(Arrays.asList("label1", "label2")), 1.0); + diskGauge.put(new ArrayList<>(Arrays.asList("label1", "label2")), innerMap); + + // Create a mock MultiGauge object + MultiGauge diskMultiGauge = mock(MultiGauge.class); + + // Call the test method + AgentHostMonitoring.multiGaugeUpdateData(diskMultiGauge, diskGauge); + + // Verify that the register method is called once + verify(diskMultiGauge, times(1)).register(anyList(), eq(true)); + } + + @Test + void testDiskMultiGaugeUpdateData() { + AgentHostMonitoring.diskMultiGaugeUpdateData(diskMultiGauge); + + // Verify that the multi-gauge update method was called + verify(diskMultiGauge, times(1)).register(anyList(), eq(true)); + } + + @Test + void testMemMultiGaugeUpdateData() { + AgentHostMonitoring.memMultiGaugeUpdateData(memMultiGauge); + + // Verify that the multi-gauge update method was called + verify(memMultiGauge, times(1)).register(anyList(), eq(true)); + } + + @Test + void testCpuMultiGaugeUpdateData() { + AgentHostMonitoring.cpuMultiGaugeUpdateData(cpuMultiGauge); + + // Verify that the multi-gauge update method was called + verify(cpuMultiGauge, times(1)).register(anyList(), eq(true)); + } + + @Test + void testDiskIOMultiGaugeUpdateData() { + AgentHostMonitoring.diskIOMultiGaugeUpdateData(diskIOMultiGauge); + + // Verify that the multi-gauge update method was called + verify(diskIOMultiGauge, times(1)).register(anyList(), eq(true)); + } +} diff --git a/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/CommandServiceGrpcImplTest.java b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/CommandServiceGrpcImplTest.java new file mode 100644 index 00000000..add9773c --- /dev/null +++ b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/CommandServiceGrpcImplTest.java @@ -0,0 +1,218 @@ +/* + * 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.agent.service; + +import org.apache.bigtop.manager.agent.executor.CommandExecutor; +import org.apache.bigtop.manager.agent.executor.CommandExecutors; +import org.apache.bigtop.manager.agent.holder.SpringContextHolder; +import org.apache.bigtop.manager.grpc.generated.CommandReply; +import org.apache.bigtop.manager.grpc.generated.CommandRequest; +import org.apache.bigtop.manager.grpc.generated.CommandType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ApplicationContext; + +import io.grpc.StatusRuntimeException; +import io.grpc.stub.StreamObserver; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class CommandServiceGrpcImplTest { + + private CommandServiceGrpcImpl commandServiceGrpc; + + @BeforeEach + public void setUp() { + SpringContextHolder springContextHolder = new SpringContextHolder(); + ApplicationContext mockApplicationContext = mock(ApplicationContext.class); + + CommandExecutor mockExecutor = mock(CommandExecutor.class); + lenient() + .when(mockApplicationContext.getBeansOfType(CommandExecutor.class)) + .thenReturn(Map.of("mockExecutor", mockExecutor)); + + springContextHolder.setApplicationContext(mockApplicationContext); + + // Initialize CommandServiceGrpcImpl + commandServiceGrpc = new CommandServiceGrpcImpl(); + } + + @Test + public void testExecCommand() { + // Arrange + CommandRequest request = CommandRequest.newBuilder() + .setPayload("Test Payload") + .setTaskId(1L) + .setType(CommandType.COMPONENT) + .build(); + + CommandReply expectedReply = CommandReply.newBuilder() + .setCode(0) + .setResult("Success") + .setTaskId(1L) + .build(); + + CommandExecutor mockExecutor = mock(CommandExecutor.class); + when(CommandExecutors.getCommandExecutor(CommandType.COMPONENT)).thenReturn(mockExecutor); + when(mockExecutor.execute(request)).thenReturn(expectedReply); + + StreamObserver responseObserver = mock(StreamObserver.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(CommandReply.class); + + // Act + commandServiceGrpc.exec(request, responseObserver); + + // Assert + verify(responseObserver).onNext(captor.capture()); + verify(responseObserver).onCompleted(); + + CommandReply actualReply = captor.getValue(); + assertEquals(expectedReply.getCode(), actualReply.getCode()); + assertEquals(expectedReply.getResult(), actualReply.getResult()); + assertEquals(expectedReply.getTaskId(), actualReply.getTaskId()); + } + + @Test + public void testExecCommandExecutorThrowsException() { + // Arrange + CommandRequest request = CommandRequest.newBuilder() + .setPayload("Test Payload") + .setTaskId(1L) + .setType(CommandType.COMPONENT) + .build(); + + when(CommandExecutors.getCommandExecutor(CommandType.COMPONENT)) + .thenThrow(new RuntimeException("Executor not found")); + + StreamObserver responseObserver = mock(StreamObserver.class); + + // Act + commandServiceGrpc.exec(request, responseObserver); + + // Assert + verify(responseObserver).onError(any(RuntimeException.class)); + } + + @Test + public void testExecCommandExecutionThrowsException() { + // Arrange + CommandRequest request = CommandRequest.newBuilder() + .setPayload("Test Payload") + .setTaskId(1L) + .setType(CommandType.COMPONENT) + .build(); + + CommandExecutor mockExecutor = mock(CommandExecutor.class); + when(CommandExecutors.getCommandExecutor(CommandType.COMPONENT)).thenReturn(mockExecutor); + when(mockExecutor.execute(request)).thenThrow(new RuntimeException("Execution failed")); + + StreamObserver responseObserver = mock(StreamObserver.class); + + // Act + commandServiceGrpc.exec(request, responseObserver); + + // Assert + verify(responseObserver).onError(any(RuntimeException.class)); + } + + @Test + public void testExecCommandLogFileOperationFails() { + // Arrange + CommandRequest request = CommandRequest.newBuilder() + .setPayload("Test Payload") + .setTaskId(1L) + .setType(CommandType.COMPONENT) + .build(); + + CommandReply expectedReply = CommandReply.newBuilder() + .setCode(1) + .setResult("File operation failed") + .setTaskId(1L) + .build(); + + CommandExecutor mockExecutor = mock(CommandExecutor.class); + lenient() + .when(CommandExecutors.getCommandExecutor(CommandType.COMPONENT)) + .thenReturn(mockExecutor); + lenient().when(mockExecutor.execute(request)).thenReturn(expectedReply); + + StreamObserver responseObserver = mock(StreamObserver.class); + + // Mock truncateLogFile to throw an exception + CommandServiceGrpcImpl commandServiceGrpcSpy = spy(commandServiceGrpc); + doThrow(new RuntimeException("File operation failed")) + .when(commandServiceGrpcSpy) + .truncateLogFile(anyLong()); + + // Act + commandServiceGrpcSpy.exec(request, responseObserver); + + // Assert + verify(responseObserver, never()).onCompleted(); + verify(responseObserver).onError(any(StatusRuntimeException.class)); + } + + @Test + public void testExecCommandResponseObserverThrowsException() { + // Arrange + CommandRequest request = CommandRequest.newBuilder() + .setPayload("Test Payload") + .setTaskId(1L) + .setType(CommandType.COMPONENT) + .build(); + + CommandReply expectedReply = CommandReply.newBuilder() + .setCode(0) + .setResult("Success") + .setTaskId(1L) + .build(); + + CommandExecutor mockExecutor = mock(CommandExecutor.class); + lenient() + .when(CommandExecutors.getCommandExecutor(CommandType.COMPONENT)) + .thenReturn(mockExecutor); + lenient().when(mockExecutor.execute(request)).thenReturn(expectedReply); + + StreamObserver responseObserver = mock(StreamObserver.class); + doThrow(new RuntimeException("Observer failed")).when(responseObserver).onNext(any()); + + // Act + commandServiceGrpc.exec(request, responseObserver); + + // Assert + verify(responseObserver, never()).onCompleted(); // Ensure onCompleted is not called + verify(responseObserver).onError(any(StatusRuntimeException.class)); + } +} diff --git a/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/ComponentStatusServiceGrpcImplTest.java b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/ComponentStatusServiceGrpcImplTest.java new file mode 100644 index 00000000..5b9b2a2f --- /dev/null +++ b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/ComponentStatusServiceGrpcImplTest.java @@ -0,0 +1,128 @@ +/* + * 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.agent.service; + +import org.apache.bigtop.manager.common.message.entity.payload.CommandPayload; +import org.apache.bigtop.manager.common.shell.ShellResult; +import org.apache.bigtop.manager.grpc.generated.ComponentStatusReply; +import org.apache.bigtop.manager.grpc.generated.ComponentStatusRequest; +import org.apache.bigtop.manager.stack.core.executor.StackExecutor; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; + +import io.grpc.Status; +import io.grpc.StatusRuntimeException; +import io.grpc.stub.StreamObserver; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +public class ComponentStatusServiceGrpcImplTest { + + private final ComponentStatusServiceGrpcImpl service = new ComponentStatusServiceGrpcImpl(); + + @Test + public void testGetComponentStatusSuccess() { + try (MockedStatic mockedStatic = mockStatic(StackExecutor.class)) { + // Arrange + ComponentStatusRequest request = ComponentStatusRequest.newBuilder() + .setStackName("TestStack") + .setStackVersion("1.0") + .setServiceName("TestService") + .setServiceUser("TestUser") + .setComponentName("TestComponent") + .build(); + + ShellResult shellResult = new ShellResult(); + shellResult.setExitCode(0); + + // Mock StackExecutor + mockedStatic + .when(() -> StackExecutor.execute(any(CommandPayload.class))) + .thenReturn(shellResult); + + StreamObserver responseObserver = mock(StreamObserver.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(ComponentStatusReply.class); + + // Act + service.getComponentStatus(request, responseObserver); + + // Assert + verify(responseObserver).onNext(captor.capture()); + verify(responseObserver).onCompleted(); + + ComponentStatusReply reply = captor.getValue(); + assertEquals(0, reply.getStatus()); + } + } + + @Test + public void testGetComponentStatusExecutionFailure() { + try (MockedStatic mockedStatic = mockStatic(StackExecutor.class)) { + // Arrange + ComponentStatusRequest request = ComponentStatusRequest.newBuilder() + .setStackName("TestStack") + .setStackVersion("1.0") + .setServiceName("TestService") + .setServiceUser("TestUser") + .setComponentName("TestComponent") + .build(); + + // Mock StackExecutor to throw an exception + mockedStatic + .when(() -> StackExecutor.execute(any(CommandPayload.class))) + .thenThrow(new RuntimeException("Execution failed")); + + StreamObserver responseObserver = mock(StreamObserver.class); + + // Act + service.getComponentStatus(request, responseObserver); + + // Assert + verify(responseObserver).onError(any(StatusRuntimeException.class)); + + // Capture the exception and verify its message + ArgumentCaptor captor = ArgumentCaptor.forClass(Throwable.class); + verify(responseObserver).onError(captor.capture()); + + // Get the captured exception + Throwable actualException = captor.getValue(); + + // Check if it is an instance of StatusRuntimeException + assertInstanceOf(StatusRuntimeException.class, actualException, "Expected StatusRuntimeException"); + + StatusRuntimeException statusRuntimeException = (StatusRuntimeException) actualException; + + // Check that the status code is UNKNOWN and the message contains the expected error message + assertEquals( + Status.UNKNOWN.getCode(), statusRuntimeException.getStatus().getCode()); + assertTrue(statusRuntimeException.getMessage().contains("Execution failed")); + } + } +} diff --git a/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/HostInfoServiceGrpcImplTest.java b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/HostInfoServiceGrpcImplTest.java new file mode 100644 index 00000000..2c4b87e9 --- /dev/null +++ b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/HostInfoServiceGrpcImplTest.java @@ -0,0 +1,121 @@ +/* + * 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.agent.service; + +import org.apache.bigtop.manager.common.utils.os.OSDetection; +import org.apache.bigtop.manager.grpc.generated.HostInfoReply; +import org.apache.bigtop.manager.grpc.generated.HostInfoRequest; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.sun.management.OperatingSystemMXBean; +import io.grpc.StatusRuntimeException; +import io.grpc.stub.StreamObserver; + +import java.lang.management.ManagementFactory; +import java.net.InetAddress; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class HostInfoServiceGrpcImplTest { + + @InjectMocks + private HostInfoServiceGrpcImpl service; + + @Test + public void testGetHostInfoSuccess() { + // Arrange + HostInfoRequest request = HostInfoRequest.newBuilder().build(); + + // Mock InetAddress + InetAddress mockInetAddress = mock(InetAddress.class); + lenient().when(mockInetAddress.getHostName()).thenReturn("localhost"); + lenient().when(mockInetAddress.getHostAddress()).thenReturn("192.168.0.100"); + + // Mock static methods of OSDetection using MockedStatic + try (MockedStatic mockedStatic = mockStatic(OSDetection.class); + MockedStatic mockManagementFactory = mockStatic(ManagementFactory.class)) { + long oneGBInBytes = 1024L * 1024L * 1024L; + long freeDiskInBytes = 100L * oneGBInBytes; + long totalDiskInBytes = 500L * oneGBInBytes; + // Mock static methods for disk size + mockedStatic.when(OSDetection::freeDisk).thenReturn(freeDiskInBytes); + mockedStatic.when(OSDetection::totalDisk).thenReturn(totalDiskInBytes); + + // Mock OSDetection static methods for OS, version, and arch + mockedStatic.when(OSDetection::getOS).thenReturn("Linux"); + mockedStatic.when(OSDetection::getVersion).thenReturn("1.0"); + mockedStatic.when(OSDetection::getArch).thenReturn("x86_64"); + + // Mock OperatingSystemMXBean methods + OperatingSystemMXBean mockOsBean = mock(OperatingSystemMXBean.class); + mockManagementFactory + .when(ManagementFactory::getOperatingSystemMXBean) + .thenReturn(mockOsBean); + when(mockOsBean.getAvailableProcessors()).thenReturn(4); + when(mockOsBean.getProcessCpuTime()).thenReturn(100L); + when(mockOsBean.getTotalMemorySize()).thenReturn(1024L * 1024 * 1024); + when(mockOsBean.getFreeMemorySize()).thenReturn(512L * 1024 * 1024); + when(mockOsBean.getTotalSwapSpaceSize()).thenReturn(2048L * 1024 * 1024); + when(mockOsBean.getFreeSwapSpaceSize()).thenReturn(1024L * 1024 * 1024); + when(mockOsBean.getCommittedVirtualMemorySize()).thenReturn(4096L * 1024 * 1024); + when(mockOsBean.getCpuLoad()).thenReturn(0.75); + when(mockOsBean.getProcessCpuLoad()).thenReturn(0.50); + when(mockOsBean.getSystemLoadAverage()).thenReturn(1.5); + + StreamObserver mockResponseObserver = mock(StreamObserver.class); + + // Act + service.getHostInfo(request, mockResponseObserver); + + // Assert + verify(mockResponseObserver).onNext(any(HostInfoReply.class)); + verify(mockResponseObserver).onCompleted(); + } + } + + @Test + public void testGetHostInfoFailure() { + // Arrange + HostInfoRequest request = HostInfoRequest.newBuilder().build(); + + try (MockedStatic mockInetAddress = mockStatic(InetAddress.class)) { + // Simulate an exception during execution + mockInetAddress.when(InetAddress::getLocalHost).thenThrow(new RuntimeException("Network error")); + + StreamObserver mockResponseObserver = mock(StreamObserver.class); + + // Act + service.getHostInfo(request, mockResponseObserver); + + // Assert + verify(mockResponseObserver).onError(any(StatusRuntimeException.class)); + } + } +} diff --git a/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/JobCacheServiceGrpcImplTest.java b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/JobCacheServiceGrpcImplTest.java new file mode 100644 index 00000000..61e13878 --- /dev/null +++ b/bigtop-manager-agent/src/test/java/org/apache/bigtop/manager/agent/service/JobCacheServiceGrpcImplTest.java @@ -0,0 +1,106 @@ +/* + * 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.agent.service; + +import org.apache.bigtop.manager.common.utils.ProjectPathUtils; +import org.apache.bigtop.manager.grpc.generated.JobCacheReply; +import org.apache.bigtop.manager.grpc.generated.JobCacheRequest; + +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.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; + +import io.grpc.stub.StreamObserver; + +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +public class JobCacheServiceGrpcImplTest { + + private JobCacheServiceGrpcImpl jobCacheServiceGrpcImpl; + + @Mock + private StreamObserver responseObserver; + + @BeforeEach + public void setUp() { + // Initialize mock objects + jobCacheServiceGrpcImpl = new JobCacheServiceGrpcImpl(); + } + + @Test + public void testSaveSuccess() { + // Mock the static behavior of ProjectPathUtils.getAgentCachePath method + try (MockedStatic mockedStatic = mockStatic(ProjectPathUtils.class)) { + String cacheDir = "mock/cache/dir"; + mockedStatic.when(ProjectPathUtils::getAgentCachePath).thenReturn(cacheDir); + + // Construct JobCacheRequest + String payloadJson = "{\"configurations\": {\"configKey\": {\"subKey\": \"subValue\"}}}"; + JobCacheRequest request = JobCacheRequest.newBuilder() + .setJobId(123L) + .setPayload(payloadJson) + .build(); + + // Execute the save method + jobCacheServiceGrpcImpl.save(request, responseObserver); + + // Verify that JsonUtils.writeToFile method was called correctly + verify(responseObserver).onNext(any(JobCacheReply.class)); + verify(responseObserver).onCompleted(); + } + } + + @Test + public void testSaveDirectoryCreationFailure() { + // Mock the static behavior of ProjectPathUtils.getAgentCachePath method + try (MockedStatic mockedStatic = mockStatic(ProjectPathUtils.class)) { + String cacheDir = "mock/cache/dir"; + mockedStatic.when(ProjectPathUtils::getAgentCachePath).thenReturn(cacheDir); + + // Mock Files.createDirectories to throw an exception + try (MockedStatic mockedFiles = mockStatic(Files.class)) { + mockedFiles + .when(() -> Files.createDirectories(any(Path.class))) + .thenThrow(new RuntimeException("Directory creation failed")); + + // Construct JobCacheRequest + String payloadJson = "{\"configurations\": {\"configKey\": {\"subKey\": \"subValue\"}}}"; + JobCacheRequest request = JobCacheRequest.newBuilder() + .setJobId(123L) + .setPayload(payloadJson) + .build(); + + // Execute the save method, expecting onError to be called + jobCacheServiceGrpcImpl.save(request, responseObserver); + + // Verify that onError was called with the expected exception + verify(responseObserver).onError(any(RuntimeException.class)); + } + } + } +}