package com.sshmanager.service; import com.sshmanager.dto.ConnectionStatusCheckRequest; import com.sshmanager.dto.ConnectionStatusResponseDto; import com.sshmanager.entity.Connection; 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.Arrays; import java.util.Collections; 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.anyInt; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class ConnectionStatusServiceTest { @Mock private ConnectionService connectionService; @Mock private TcpProbe tcpProbe; private ConnectionStatusService connectionStatusService; @BeforeEach void setUp() { connectionStatusService = new ConnectionStatusService(connectionService, tcpProbe); } @Test void checkStatusesRejectsEmptyConnectionIds() { ConnectionStatusCheckRequest request = new ConnectionStatusCheckRequest(); IllegalArgumentException error = assertThrows( IllegalArgumentException.class, () -> connectionStatusService.checkStatuses(1L, request) ); assertEquals("At least one connection is required", error.getMessage()); } @Test void checkStatusesMarksReachableAsOnline() throws Exception { Connection conn = new Connection(); conn.setId(1L); conn.setUserId(99L); conn.setName("reachable-host"); conn.setHost("10.0.0.1"); conn.setPort(22); when(connectionService.getConnectionForSsh(1L, 99L)).thenReturn(conn); ConnectionStatusCheckRequest request = new ConnectionStatusCheckRequest(); request.setConnectionIds(Arrays.asList(1L)); ConnectionStatusResponseDto response = connectionStatusService.checkStatuses(99L, request); assertEquals(1, response.getTotal()); assertEquals(1, response.getOnlineCount()); assertEquals(0, response.getOfflineCount()); assertEquals("online", response.getResults().get(0).getStatus()); assertEquals("TCP port reachable", response.getResults().get(0).getMessage()); } @Test void checkStatusesMarksUnreachableAsOffline() throws Exception { Connection conn = new Connection(); conn.setId(2L); conn.setUserId(99L); conn.setName("unreachable-host"); conn.setHost("10.0.0.2"); conn.setPort(22); when(connectionService.getConnectionForSsh(2L, 99L)).thenReturn(conn); doAnswer(invocation -> { throw new RuntimeException("Connection refused"); }) .when(tcpProbe).checkReachable(conn, 5); ConnectionStatusCheckRequest request = new ConnectionStatusCheckRequest(); request.setConnectionIds(Arrays.asList(2L)); ConnectionStatusResponseDto response = connectionStatusService.checkStatuses(99L, request); assertEquals(1, response.getTotal()); assertEquals(0, response.getOnlineCount()); assertEquals(1, response.getOfflineCount()); assertEquals("offline", response.getResults().get(0).getStatus()); } @Test void checkStatusesAggregatesMixedResults() throws Exception { Connection online = new Connection(); online.setId(10L); online.setUserId(99L); online.setName("server-a"); online.setHost("10.0.0.1"); online.setPort(22); Connection offline = new Connection(); offline.setId(20L); offline.setUserId(99L); offline.setName("server-b"); offline.setHost("10.0.0.2"); offline.setPort(22); when(connectionService.getConnectionForSsh(10L, 99L)).thenReturn(online); when(connectionService.getConnectionForSsh(20L, 99L)).thenReturn(offline); // Answer with argument matching based on connection ID doAnswer(invocation -> { Connection c = invocation.getArgument(0); if (c.getId() == 20L) throw new RuntimeException("Connection refused"); return null; }).when(tcpProbe).checkReachable(any(Connection.class), anyInt()); ConnectionStatusCheckRequest request = new ConnectionStatusCheckRequest(); request.setConnectionIds(Arrays.asList(10L, 20L)); ConnectionStatusResponseDto response = connectionStatusService.checkStatuses(99L, request); assertEquals(2, response.getTotal()); assertEquals(1, response.getOnlineCount()); assertEquals(1, response.getOfflineCount()); } @Test void checkStatusesHandlesAllOfflineGracefully() throws Exception { Connection conn = new Connection(); conn.setId(99L); conn.setUserId(99L); conn.setName("fail-host"); conn.setHost("10.0.0.1"); conn.setPort(22); when(connectionService.getConnectionForSsh(99L, 99L)).thenReturn(conn); doAnswer(invocation -> { throw new RuntimeException("timeout"); }) .when(tcpProbe).checkReachable(conn, 5); ConnectionStatusCheckRequest request = new ConnectionStatusCheckRequest(); request.setConnectionIds(Collections.singletonList(99L)); ConnectionStatusResponseDto response = connectionStatusService.checkStatuses(99L, request); assertEquals(1, response.getTotal()); assertEquals(0, response.getOnlineCount()); assertEquals(1, response.getOfflineCount()); } }