/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* 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 org.kie.workbench.common.screens.projecteditor.client.build;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Sets;
import com.google.gwtmockito.GwtMockitoTestRunner;
import org.guvnor.common.services.project.builder.model.BuildMessage;
import org.guvnor.common.services.project.builder.model.BuildResults;
import org.guvnor.common.services.project.builder.service.BuildService;
import org.guvnor.common.services.project.client.repositories.ConflictingRepositoriesPopup;
import org.guvnor.common.services.project.context.ProjectContext;
import org.guvnor.common.services.project.model.GAV;
import org.guvnor.common.services.project.model.POM;
import org.guvnor.common.services.project.service.DeploymentMode;
import org.guvnor.common.services.project.service.GAVAlreadyExistsException;
import org.guvnor.structure.repositories.Repository;
import org.jboss.errai.common.client.api.Caller;
import org.jboss.errai.common.client.api.ErrorCallback;
import org.jboss.errai.common.client.api.RemoteCallback;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.server.controller.api.model.spec.ContainerSpec;
import org.kie.server.controller.api.model.spec.ServerTemplate;
import org.kie.workbench.common.screens.projecteditor.client.editor.DeploymentScreenPopupViewImpl;
import org.kie.workbench.common.screens.projecteditor.client.resources.ProjectEditorResources;
import org.kie.workbench.common.screens.server.management.service.SpecManagementService;
import org.kie.workbench.common.services.shared.project.KieProject;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.uberfire.backend.vfs.Path;
import org.uberfire.mocks.CallerMock;
import org.uberfire.mocks.EventSourceMock;
import org.uberfire.mvp.Command;
import org.uberfire.workbench.events.NotificationEvent;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
@RunWith(GwtMockitoTestRunner.class)
public class BuildExecutorTest {
@Mock
private DeploymentScreenPopupViewImpl deploymentScreenPopupView;
@Mock
private SpecManagementService specManagementServiceMock;
private Caller<SpecManagementService> specManagementService;
@Mock
private BuildService buildServiceMock;
private Caller<BuildService> buildService;
@Mock
private EventSourceMock<BuildResults> buildResultsEvent;
@Mock
private EventSourceMock<NotificationEvent> notificationEvent;
@Mock
private ConflictingRepositoriesPopup conflictingRepositoriesPopup;
@Mock
private ProjectContext context;
@Mock
protected Repository repository;
@Mock
protected KieProject project;
@Mock
protected Path pomPath;
@Mock
private BuildExecutor.View view;
private BuildExecutor buildExecutor;
@Before
public void setup() {
specManagementService = new CallerMock<>(specManagementServiceMock);
buildService = spy(new CallerMock<>(buildServiceMock));
final POM pom = new POM(new GAV("groupId",
"artifactId",
"version"));
mockBuildService(buildServiceMock);
mockProjectContext(pom,
repository,
project,
pomPath);
buildExecutor = new BuildExecutor(deploymentScreenPopupView,
specManagementService,
buildService,
buildResultsEvent,
notificationEvent,
conflictingRepositoriesPopup,
context);
buildExecutor.init(view);
}
@Test
public void testBuildCommand() {
buildExecutor.triggerBuild();
verifyNotification(ProjectEditorResources.CONSTANTS.BuildSuccessful(),
NotificationEvent.NotificationType.SUCCESS);
verifyBusyShowHideAnyString(1,
1,
ProjectEditorResources.CONSTANTS.Building());
}
@Test
public void testBuildCommandFail() {
BuildMessage message = mock(BuildMessage.class);
List<BuildMessage> messages = new ArrayList<BuildMessage>();
messages.add(message);
BuildResults results = mock(BuildResults.class);
when(results.getErrorMessages()).thenReturn(messages);
when(buildServiceMock.build(any(KieProject.class))).thenReturn(results);
buildExecutor.triggerBuild();
verifyNotification(ProjectEditorResources.CONSTANTS.BuildFailed(),
NotificationEvent.NotificationType.ERROR);
verifyBusyShowHideAnyString(1,
1,
ProjectEditorResources.CONSTANTS.Building());
}
@Test
public void testBuildAndDeployCommandSingleServerTemplate() {
final ServerTemplate serverTemplate = new ServerTemplate("id",
"name");
when(specManagementServiceMock.listServerTemplates()).thenReturn(Collections.singletonList(serverTemplate));
buildExecutor.triggerBuildAndDeploy();
ArgumentCaptor<ContainerSpec> containerSpecArgumentCaptor = ArgumentCaptor.forClass(ContainerSpec.class);
verify(specManagementServiceMock).saveContainerSpec(eq(serverTemplate.getId()),
containerSpecArgumentCaptor.capture());
final ContainerSpec containerSpec = containerSpecArgumentCaptor.getValue();
assertEquals(project.getPom().getGav().getArtifactId(),
containerSpec.getContainerName());
verifyNotification(ProjectEditorResources.CONSTANTS.BuildSuccessful(),
NotificationEvent.NotificationType.SUCCESS);
verifyNotification(ProjectEditorResources.CONSTANTS.DeploySuccessful(),
NotificationEvent.NotificationType.SUCCESS);
verify(notificationEvent,
times(2)).fire(any(NotificationEvent.class));
verifyBusyShowHideAnyString(1,
1);
}
@Test
public void testBuildAndDeployCommandSingleServerTemplateContainerExists() {
final String containerId = project.getPom().getGav().getArtifactId() + "_" + project.getPom().getGav().getVersion();
final String containerName = project.getPom().getGav().getArtifactId();
final ServerTemplate serverTemplate = new ServerTemplate("id",
"name");
serverTemplate.addContainerSpec(new ContainerSpec(containerId,
containerName,
null,
null,
null,
null));
when(specManagementServiceMock.listServerTemplates()).thenReturn(Collections.singletonList(serverTemplate));
buildExecutor.triggerBuildAndDeploy();
verify(deploymentScreenPopupView).setValidateExistingContainerCallback(any(DeploymentScreenPopupViewImpl.ValidateExistingContainerCallback.class));
verify(deploymentScreenPopupView).setContainerId(containerId);
verify(deploymentScreenPopupView).setContainerAlias(containerName);
verify(deploymentScreenPopupView).setStartContainer(true);
verify(deploymentScreenPopupView).configure(any(com.google.gwt.user.client.Command.class));
verify(deploymentScreenPopupView).show();
verifyNoMoreInteractions(deploymentScreenPopupView);
}
@Test
public void testBuildAndDeployCommandMultipleServerTemplate() {
final String containerId = project.getPom().getGav().getArtifactId() + "_" + project.getPom().getGav().getVersion();
final String containerName = project.getPom().getGav().getArtifactId();
final ServerTemplate serverTemplate1 = new ServerTemplate("id1",
"name1");
final ServerTemplate serverTemplate2 = new ServerTemplate("id2",
"name2");
when(specManagementServiceMock.listServerTemplates()).thenReturn(Arrays.asList(serverTemplate1,
serverTemplate2));
buildExecutor.triggerBuildAndDeploy();
verify(deploymentScreenPopupView).setValidateExistingContainerCallback(any(DeploymentScreenPopupViewImpl.ValidateExistingContainerCallback.class));
verify(deploymentScreenPopupView).setContainerId(containerId);
verify(deploymentScreenPopupView).setContainerAlias(containerName);
verify(deploymentScreenPopupView).setStartContainer(true);
verify(deploymentScreenPopupView).addServerTemplates(eq(Sets.newHashSet("id1",
"id2")));
verify(deploymentScreenPopupView).configure(any(com.google.gwt.user.client.Command.class));
verify(deploymentScreenPopupView).show();
verifyNoMoreInteractions(deploymentScreenPopupView);
}
@Test
public void testBuildAndDeployCommand() {
buildExecutor.triggerBuildAndDeploy();
verifyNotification(ProjectEditorResources.CONSTANTS.BuildSuccessful(),
NotificationEvent.NotificationType.SUCCESS);
verify(notificationEvent,
times(1)).fire(any(NotificationEvent.class));
verifyBusyShowHideAnyString(1,
1);
}
@Test
public void testBuildAndDeployCommandFail() {
BuildMessage message = mock(BuildMessage.class);
List<BuildMessage> messages = new ArrayList<>();
messages.add(message);
BuildResults results = mock(BuildResults.class);
when(results.getErrorMessages()).thenReturn(messages);
when(buildServiceMock.buildAndDeploy(any(KieProject.class),
any(DeploymentMode.class))).thenReturn(results);
buildExecutor.triggerBuildAndDeploy();
verifyNotification(ProjectEditorResources.CONSTANTS.BuildFailed(),
NotificationEvent.NotificationType.ERROR);
verifyBusyShowHideAnyString(1,
1,
ProjectEditorResources.CONSTANTS.Building());
}
@Test
public void testAlreadyRunningBuild() {
when(buildService.call(any(RemoteCallback.class),
any(ErrorCallback.class))).thenAnswer(invocationOnMock -> {
// not calling callback causes building is still set to true
return buildServiceMock;
});
buildExecutor.triggerBuild();
buildExecutor.triggerBuild();
verify(view,
times(1)).showABuildIsAlreadyRunning();
verify(notificationEvent,
never()).fire(any(NotificationEvent.class));
verifyBusyShowHideAnyString(1,
0);
}
@Test
public void testAlreadyRunningBuildAndDeploy() {
when(buildService.call(any(RemoteCallback.class),
any(ErrorCallback.class))).thenAnswer(invocationOnMock -> {
// not calling callback causes building is still set to true
return buildServiceMock;
});
buildExecutor.triggerBuildAndDeploy();
buildExecutor.triggerBuildAndDeploy();
verify(view,
times(1)).showABuildIsAlreadyRunning();
verify(notificationEvent,
never()).fire(any(NotificationEvent.class));
verifyBusyShowHideAnyString(1,
0);
}
@Test
public void testBuildManagedRepository() throws Exception {
final Map<String, Object> env = new HashMap<String, Object>() {
{
put("managed",
true);
}
};
when(repository.getEnvironment()).thenReturn(env);
buildExecutor.triggerBuild();
verify(buildServiceMock,
times(1)).build(eq(project));
verifyBusyShowHideAnyString(1,
1,
ProjectEditorResources.CONSTANTS.Building());
}
@Test
public void testBuildNotManagedRepositoryNonClashingGAV() throws Exception {
final Map<String, Object> env = new HashMap<String, Object>() {
{
put("managed",
false);
}
};
when(repository.getEnvironment()).thenReturn(env);
buildExecutor.triggerBuild();
verify(buildServiceMock,
times(1)).build(eq(project));
verifyBusyShowHideAnyString(1,
1,
ProjectEditorResources.CONSTANTS.Building());
}
@Test
@SuppressWarnings("unchecked")
public void testBuildNotManagedRepositoryClashingGAV() throws Exception {
final Map<String, Object> env = new HashMap<String, Object>() {
{
put("managed",
false);
}
};
when(repository.getEnvironment()).thenReturn(env);
doThrow(GAVAlreadyExistsException.class).when(buildServiceMock).buildAndDeploy(eq(project),
eq(DeploymentMode.VALIDATED));
final GAV gav = project.getPom().getGav();
final ArgumentCaptor<Command> commandArgumentCaptor = ArgumentCaptor.forClass(Command.class);
buildExecutor.triggerBuildAndDeploy();
verify(buildServiceMock,
times(1)).buildAndDeploy(eq(project),
eq(DeploymentMode.VALIDATED));
verify(conflictingRepositoriesPopup,
times(1)).setContent(eq(gav),
any(Set.class),
commandArgumentCaptor.capture());
verify(conflictingRepositoriesPopup,
times(1)).show();
assertNotNull(commandArgumentCaptor.getValue());
//Emulate User electing to force save
commandArgumentCaptor.getValue().execute();
verify(conflictingRepositoriesPopup,
times(1)).hide();
verify(buildServiceMock,
times(1)).buildAndDeploy(eq(project),
eq(DeploymentMode.FORCED));
verify(view,
times(2)).showBusyIndicator(eq(ProjectEditorResources.CONSTANTS.Building()));
verify(view,
times(2)).hideBusyIndicator();
}
private void verifyNotification(final String message,
final NotificationEvent.NotificationType type) {
verify(notificationEvent).fire(argThat(new ArgumentMatcher<NotificationEvent>() {
@Override
public boolean matches(final Object argument) {
final NotificationEvent event = (NotificationEvent) argument;
final String notification = event.getNotification();
final NotificationEvent.NotificationType type = event.getType();
return notification.equals(message) && type.equals(type);
}
}));
}
private void verifyBusyShowHideAnyString(final int show,
final int hide) {
verifyBusyShowHideAnyString(show,
hide,
null);
}
private void verifyBusyShowHideAnyString(final int show,
final int hide,
final String message) {
if (message != null) {
verify(view,
times(show)).showBusyIndicator(message);
} else {
verify(view,
times(show)).showBusyIndicator(anyString());
}
verify(view,
times(hide)).hideBusyIndicator();
}
private void mockProjectContext(final POM pom,
final Repository repository,
final KieProject project,
final Path pomPath) {
when(context.getActiveRepository()).thenReturn(repository);
when(context.getActiveBranch()).thenReturn("master");
when(repository.getAlias()).thenReturn("repository");
when(project.getProjectName()).thenReturn("project");
when(project.getPomXMLPath()).thenReturn(pomPath);
when(project.getPom()).thenReturn(pom);
when(project.getRootPath()).thenReturn(mock(Path.class));
when(pomPath.getFileName()).thenReturn("pom.xml");
when(context.getActiveProject()).thenReturn(project);
}
private void mockBuildService(final BuildService buildService) {
when(buildService.build(any(KieProject.class))).thenReturn(new BuildResults());
when(buildService.buildAndDeploy(any(KieProject.class),
any(DeploymentMode.class))).thenReturn(new BuildResults());
}
}