/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.api.agent; import org.eclipse.che.api.agent.server.WsAgentPingRequestFactory; import org.eclipse.che.api.agent.shared.model.Agent; import org.eclipse.che.api.core.BadRequestException; import org.eclipse.che.api.core.NotFoundException; import org.eclipse.che.api.core.ServerException; import org.eclipse.che.api.core.model.machine.Command; import org.eclipse.che.api.core.model.machine.Server; import org.eclipse.che.api.core.rest.HttpJsonRequest; import org.eclipse.che.api.core.rest.HttpJsonRequestFactory; import org.eclipse.che.api.core.rest.HttpJsonResponse; import org.eclipse.che.api.environment.server.MachineProcessManager; import org.eclipse.che.api.machine.server.exception.MachineException; import org.eclipse.che.api.machine.server.model.impl.CommandImpl; import org.eclipse.che.api.machine.server.model.impl.MachineRuntimeInfoImpl; import org.eclipse.che.api.machine.server.model.impl.ServerImpl; import org.eclipse.che.api.machine.server.model.impl.ServerPropertiesImpl; import org.eclipse.che.api.machine.server.spi.Instance; import org.eclipse.che.api.machine.server.spi.InstanceNode; import org.eclipse.che.api.machine.shared.Constants; import org.eclipse.che.commons.test.mockito.answer.SelfReturningAnswer; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.testng.MockitoTestNGListener; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import java.io.IOException; import java.net.HttpURLConnection; import java.util.Collections; import static org.eclipse.che.api.workspace.shared.Constants.WS_AGENT_PROCESS_NAME; @Listeners(MockitoTestNGListener.class) public class WsAgentLauncherTest { private static final String MACHINE_ID = "machineId"; private static final String WORKSPACE_ID = "testWorkspaceId"; private static final String WS_AGENT_PORT = Constants.WS_AGENT_PORT; private static final long WS_AGENT_MAX_START_TIME_MS = 1000; private static final long WS_AGENT_PING_DELAY_MS = 1; private static final String WS_AGENT_SERVER_LOCATION = "ws-agent.com:456789/"; private static final String WS_AGENT_SERVER_URL = "http://" + WS_AGENT_SERVER_LOCATION; private static final String WS_AGENT_SERVER_LOCATION_EXT = "ws-agent-ext.com:456789/"; private static final String WS_AGENT_SERVER_URL_EXT = "http://" + WS_AGENT_SERVER_LOCATION; private static final ServerPropertiesImpl SERVER_PROPERTIES = new ServerPropertiesImpl(null, WS_AGENT_SERVER_LOCATION, WS_AGENT_SERVER_URL); private static final ServerImpl SERVER = new ServerImpl("ref", "http", WS_AGENT_SERVER_LOCATION_EXT, WS_AGENT_SERVER_URL_EXT, SERVER_PROPERTIES); private static final String WS_AGENT_TIMED_OUT_MESSAGE = "timeout error message"; @Mock private MachineProcessManager machineProcessManager; @Mock private HttpJsonRequestFactory requestFactory; @Mock private Instance machine; @Mock private HttpJsonResponse pingResponse; @Mock private MachineRuntimeInfoImpl machineRuntime; @Mock private WsAgentPingRequestFactory wsAgentPingRequestFactory; @Mock private Agent agent; private HttpJsonRequest pingRequest; private WsAgentLauncher wsAgentLauncher; @BeforeMethod public void setUp() throws Exception { wsAgentLauncher = new WsAgentLauncher(() -> machineProcessManager, wsAgentPingRequestFactory, null, WS_AGENT_MAX_START_TIME_MS, WS_AGENT_PING_DELAY_MS, WS_AGENT_TIMED_OUT_MESSAGE ); pingRequest = Mockito.mock(HttpJsonRequest.class, new SelfReturningAnswer()); Mockito.when(agent.getScript()).thenReturn("script"); Mockito.when(machine.getId()).thenReturn(MACHINE_ID); Mockito.when(machine.getWorkspaceId()).thenReturn(WORKSPACE_ID); Mockito.when(machine.getRuntime()).thenReturn(machineRuntime); Mockito.when(machine.getNode()).thenReturn(Mockito.mock(InstanceNode.class)); Mockito.doReturn(Collections.<String, Server>singletonMap(WS_AGENT_PORT, SERVER)).when(machineRuntime).getServers(); Mockito.when(requestFactory.fromUrl(Matchers.anyString())).thenReturn(pingRequest); Mockito.when(wsAgentPingRequestFactory.createRequest(machine)).thenReturn(pingRequest); Mockito.when(pingRequest.request()).thenReturn(pingResponse); Mockito.when(pingResponse.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK); } @Test public void shouldStartWsAgentUsingMachineExec() throws Exception { wsAgentLauncher.launch(machine, agent); Mockito.verify(machineProcessManager).exec(Matchers.eq(WORKSPACE_ID), Matchers.eq(MACHINE_ID), Matchers.eq(new CommandImpl("org.eclipse.che.ws-agent", "script\n" + WsAgentLauncher.DEFAULT_WS_AGENT_RUN_COMMAND, WS_AGENT_PROCESS_NAME)), Matchers.eq(WsAgentLauncher.getWsAgentProcessOutputChannel(WORKSPACE_ID))); } @Test public void shouldPingWsAgentAfterStart() throws Exception { wsAgentLauncher.launch(machine, agent); Mockito.verify(pingRequest).request(); Mockito.verify(pingResponse).getResponseCode(); } @Test public void shouldPingWsAgentMultipleTimesAfterStartIfPingFailsWithException() throws Exception { Mockito.when(pingRequest.request()).thenThrow(new ServerException(""), new BadRequestException(""), new IOException()) .thenReturn(pingResponse); wsAgentLauncher.launch(machine, agent); Mockito.verify(pingRequest, Mockito.times(4)).request(); Mockito.verify(pingResponse).getResponseCode(); } @Test public void shouldPingWsAgentMultipleTimesAfterStartIfPingReturnsNotOKResponseCode() throws Exception { Mockito.when(pingResponse.getResponseCode()).thenReturn(HttpURLConnection.HTTP_CREATED, HttpURLConnection.HTTP_NO_CONTENT, HttpURLConnection.HTTP_OK); wsAgentLauncher.launch(machine, agent); Mockito.verify(pingRequest, Mockito.times(3)).request(); Mockito.verify(pingResponse, Mockito.times(3)).getResponseCode(); } @Test public void shouldNotPingWsAgentAfterFirstSuccessfulPing() throws Exception { Mockito.when(pingRequest.request()).thenThrow(new ServerException("")) .thenReturn(pingResponse); wsAgentLauncher.launch(machine, agent); Mockito.verify(pingRequest, Mockito.times(2)).request(); Mockito.verify(pingResponse).getResponseCode(); } @Test(expectedExceptions = ServerException.class, expectedExceptionsMessageRegExp = "Test exception") public void shouldThrowMachineExceptionIfMachineManagerExecInDevMachineThrowsNotFoundException() throws Exception { Mockito.when(machineProcessManager.exec(Matchers.anyString(), Matchers.anyString(), Matchers.any(Command.class), Matchers.anyString())) .thenThrow(new NotFoundException("Test exception")); wsAgentLauncher.launch(machine, agent); Mockito.verify(machineProcessManager).exec(Matchers.anyString(), Matchers.anyString(), Matchers.any(Command.class), Matchers.anyString()); } @Test(expectedExceptions = ServerException.class, expectedExceptionsMessageRegExp = "Test exception") public void shouldThrowMachineExceptionIfMachineManagerExecInDevMachineThrowsMachineException() throws Exception { Mockito.when(machineProcessManager.exec(Matchers.anyString(), Matchers.anyString(), Matchers.any(Command.class), Matchers.anyString())) .thenThrow(new MachineException("Test exception")); wsAgentLauncher.launch(machine, agent); Mockito.verify(machineProcessManager).exec(Matchers.anyString(), Matchers.anyString(), Matchers.any(Command.class), Matchers.anyString()); } @Test(expectedExceptions = ServerException.class, expectedExceptionsMessageRegExp = "Test exception") public void shouldThrowExceptionIfMachineManagerExecInDevMachineThrowsBadRequestException() throws Exception { Mockito.when(machineProcessManager.exec(Matchers.anyString(), Matchers.anyString(), Matchers.any(Command.class), Matchers.anyString())) .thenThrow(new BadRequestException("Test exception")); wsAgentLauncher.launch(machine, agent); Mockito.verify(machineProcessManager).exec(Matchers.anyString(), Matchers.anyString(), Matchers.any(Command.class), Matchers.anyString()); } @Test(expectedExceptions = ServerException.class, expectedExceptionsMessageRegExp = WS_AGENT_TIMED_OUT_MESSAGE) public void shouldThrowMachineExceptionIfPingsWereUnsuccessfulTooLong() throws Exception { Mockito.when(pingRequest.request()).thenThrow(new ServerException("")); wsAgentLauncher.launch(machine, agent); } }