diff options
Diffstat (limited to 'catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java')
-rw-r--r-- | catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java new file mode 100644 index 0000000000..2c3d411922 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java @@ -0,0 +1,452 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.servlets; + +import fj.data.Either; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.openecomp.sdc.be.components.impl.ArchiveBusinessLogic; +import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; +import org.openecomp.sdc.be.components.path.utils.GraphTestUtils; +import org.openecomp.sdc.be.components.validation.AccessValidations; +import org.openecomp.sdc.be.components.validation.ComponentValidations; +import org.openecomp.sdc.be.config.ConfigurationManager; +import org.openecomp.sdc.be.dao.DAOTitanStrategy; +import org.openecomp.sdc.be.dao.TitanClientStrategy; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; +import org.openecomp.sdc.be.dao.jsongraph.TitanDao; +import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; +import org.openecomp.sdc.be.dao.titan.TitanGenericDao; +import org.openecomp.sdc.be.dao.titan.TitanGraphClient; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.enums.*; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.impl.ServletUtils; +import org.openecomp.sdc.be.impl.WebAppContextWrapper; +import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.catalog.CatalogComponent; +import org.openecomp.sdc.be.model.jsontitan.operations.*; +import org.openecomp.sdc.be.model.operations.api.ICacheMangerOperation; +import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.servlets.exception.ComponentExceptionMapper; +import org.openecomp.sdc.be.servlets.exception.DefaultExceptionMapper; +import org.openecomp.sdc.be.servlets.exception.StorageExceptionMapper; +import org.openecomp.sdc.be.user.Role; +import org.openecomp.sdc.be.user.UserBusinessLogic; +import org.openecomp.sdc.common.api.ConfigurationSource; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.impl.ExternalConfiguration; +import org.openecomp.sdc.common.impl.FSConfigurationSource; +import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; +import org.springframework.web.context.WebApplicationContext; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +public class ArchiveEndpointTest extends JerseyTest { + + private static final ServletContext servletContext = mock(ServletContext.class); + private static final String CSAR_UUID1 = "123456789abcdefgh"; + private static final String CSAR_UUID2 = "987654321abcdefgh"; + + public static final WebAppContextWrapper webAppContextWrapper = mock(WebAppContextWrapper.class); + private static final WebApplicationContext webApplicationContext = mock(WebApplicationContext.class); + private static final ServletUtils servletUtils = mock(ServletUtils.class); + private static final UserBusinessLogic userAdmin = mock(UserBusinessLogic.class); + private static final ComponentsUtils componentUtils = mock(ComponentsUtils.class); + private static final ResponseFormat responseFormat = mock(ResponseFormat.class); + private static final ResponseFormat notFoundResponseFormat = mock(ResponseFormat.class); + private static final ResponseFormat badRequestResponseFormat = mock(ResponseFormat.class); + private static final ResponseFormat invalidServiceStateResponseFormat = mock(ResponseFormat.class); + private static final AccessValidations accessValidationsMock = mock(AccessValidations.class); + private static final ComponentValidations componentValidationsMock = mock(ComponentValidations.class); + private static final IGraphLockOperation graphLockOperation = mock(IGraphLockOperation.class); + private static final TitanGenericDao titanGenericDao = mock(TitanGenericDao.class); + + private static final ICacheMangerOperation cacheManagerOperation = mock(ICacheMangerOperation.class); + private static GraphVertex serviceVertex; + private static GraphVertex resourceVertex; + private static GraphVertex resourceVertexVspArchived; + + private static TitanDao titanDao; + + @Configuration + static class TestSpringConfig { + private ArchiveOperation archiveOperation; + private GraphVertex catalogVertex; + + @Bean + ArchiveEndpoint archiveEndpoint() { + return new ArchiveEndpoint(archiveBusinessLogic()); + } + + @Bean + ComponentExceptionMapper componentExceptionMapper() { + return new ComponentExceptionMapper(componentUtils); + } + + @Bean + StorageExceptionMapper storageExceptionMapper() { + return new StorageExceptionMapper(componentUtils); + } + + @Bean + DefaultExceptionMapper defaultExceptionMapper() { + return new DefaultExceptionMapper(); + } + + @Bean + ArchiveBusinessLogic archiveBusinessLogic() { + return new ArchiveBusinessLogic(titanDao(), accessValidations(), archiveOperation(), toscaOperationFacade(), componentUtils); + } + + @Bean + ArchiveOperation archiveOperation() { + this.archiveOperation = new ArchiveOperation(titanDao(), graphLockOperation()); + GraphTestUtils.clearGraph(titanDao); + initGraphForTest(); + return this.archiveOperation; + } + + @Bean + ComponentValidations componentValidations() { + return componentValidationsMock; + } + + @Bean + AccessValidations accessValidations() { + return accessValidationsMock; + } + + @Bean + ToscaOperationFacade toscaOperationFacade() { + return new ToscaOperationFacade(); + } + + @Bean + TopologyTemplateOperation topologyTemplateOperation() { + return new TopologyTemplateOperation(); + } + + @Bean + NodeTypeOperation nodeTypeOpertaion() { + return new NodeTypeOperation(null); + } + + @Bean + NodeTemplateOperation nodeTemplateOperation() { + return new NodeTemplateOperation(); + } + + @Bean + GroupsOperation groupsOperation() { + return new GroupsOperation(); + } + + @Bean + ICacheMangerOperation cacheMangerOperation() { + return cacheManagerOperation; + } + + @Bean + TitanDao titanDao() { + titanDao = new TitanDao(titanGraphClient()); + return titanDao; + } + + @Bean + TitanGraphClient titanGraphClient() { + return new TitanGraphClient(titanClientStrategy()); + } + + @Bean + TitanClientStrategy titanClientStrategy() { + return new DAOTitanStrategy(); + } + + @Bean + CategoryOperation categoryOperation() { + return new CategoryOperation(); + } + + @Bean + IGraphLockOperation graphLockOperation() { + return graphLockOperation; + } + + @Bean + TitanGenericDao titanGenericDao() { + return titanGenericDao; + } + + private void initGraphForTest() { + //Create Catalog Root + catalogVertex = GraphTestUtils.createRootCatalogVertex(titanDao); + //Create Archive Root + GraphTestUtils.createRootArchiveVertex(titanDao); + + createSingleVersionServiceAndResource(); + } + + private void createSingleVersionServiceAndResource() { + //Create Service for Scenario 1 Tests (1 Service) + serviceVertex = GraphTestUtils.createServiceVertex(titanDao, propsForHighestVersion()); + + + Map<GraphPropertyEnum, Object> props = propsForHighestVersion(); + props.put(GraphPropertyEnum.IS_VSP_ARCHIVED, false); + props.put(GraphPropertyEnum.CSAR_UUID, CSAR_UUID1); + resourceVertex = GraphTestUtils.createResourceVertex(titanDao, props, ResourceTypeEnum.VF); + + props = propsForHighestVersion(); + props.put(GraphPropertyEnum.IS_VSP_ARCHIVED, true); + props.put(GraphPropertyEnum.CSAR_UUID, CSAR_UUID2); + resourceVertexVspArchived = GraphTestUtils.createResourceVertex(titanDao, props, ResourceTypeEnum.VF); + + //Connect Service/Resource to Catalog Root + titanDao.createEdge(catalogVertex, serviceVertex, EdgeLabelEnum.CATALOG_ELEMENT, null); + titanDao.createEdge(catalogVertex, resourceVertex, EdgeLabelEnum.CATALOG_ELEMENT, null); + } + + private Map<GraphPropertyEnum, Object> propsForHighestVersion(){ + Map<GraphPropertyEnum, Object> props = new HashMap<>(); + props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + return props; + } + } + + public static final HttpServletRequest request = mock(HttpServletRequest.class); + + /* Users */ + private static final User adminUser = new User("admin", "admin", "admin", "admin@email.com", Role.ADMIN.name(), System.currentTimeMillis()); + private static final User designerUser = new User("designer", "designer", "designer", "designer@email.com", Role.DESIGNER.name(), System + .currentTimeMillis()); + private static final User otherUser = new User("other", "other", "other", "other@email.com", Role.OPS.name(), System.currentTimeMillis()); + + @BeforeClass + public static void setup() { + //Needed for User Authorization + //======================================================================================================================== + when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR)).thenReturn(webAppContextWrapper); + when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext); + when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils); + when(servletUtils.getUserAdmin()).thenReturn(userAdmin); + when(servletUtils.getComponentsUtils()).thenReturn(componentUtils); + when(componentUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)).thenReturn(responseFormat); + when(componentUtils.getResponseFormat(eq(ActionStatus.INVALID_SERVICE_STATE), any())).thenReturn(invalidServiceStateResponseFormat); + when(responseFormat.getStatus()).thenReturn(HttpStatus.UNAUTHORIZED.value()); + + ComponentException ce = new ComponentException(responseFormat); + doThrow(ce).when(accessValidationsMock).userIsAdminOrDesigner(eq(otherUser.getUserId()), any()); + + //Needed for error configuration + when(notFoundResponseFormat.getStatus()).thenReturn(HttpStatus.NOT_FOUND.value()); + when(invalidServiceStateResponseFormat.getStatus()).thenReturn(HttpStatus.CONFLICT.value()); + when(badRequestResponseFormat.getStatus()).thenReturn(HttpStatus.BAD_REQUEST.value()); + when(componentUtils.getResponseFormat(eq(ActionStatus.RESOURCE_NOT_FOUND), (String[]) any())).thenReturn(notFoundResponseFormat); + when(componentUtils.getResponseFormat(eq(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID), (String[]) any())).thenReturn(badRequestResponseFormat); + + when(graphLockOperation.lockComponent(anyString(), any(NodeTypeEnum.class))).thenReturn(StorageOperationStatus.OK); + + Either<User, ActionStatus> adminEither = Either.left(adminUser); + Either<User, ActionStatus> designerEither = Either.left(designerUser); + Either<User, ActionStatus> otherEither = Either.left(otherUser); + + when(userAdmin.getUser(adminUser.getUserId(), false)).thenReturn(adminEither); + when(userAdmin.getUser(designerUser.getUserId(), false)).thenReturn(designerEither); + when(userAdmin.getUser(otherUser.getUserId(), false)).thenReturn(otherEither); + //======================================================================================================================== + + String appConfigDir = "src/test/resources/config"; + ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir); + ConfigurationManager configurationManager = new ConfigurationManager(configurationSource); + + org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration(); + configuration.setTitanInMemoryGraph(true); + + configurationManager.setConfiguration(configuration); + ExternalConfiguration.setAppName("catalog-be"); + } + + @Test + public void getArchivedComponents_Empty() { + assertOnGetArchivedComponents(null, 0); + } + + @Test + public void archiveAndGetArchivedComponents_SingleComponent() { + archiveComponent(serviceVertex.getUniqueId(), HttpStatus.OK.value()); + assertOnGetArchivedComponents(ComponentTypeEnum.SERVICE_PARAM_NAME, 1); + } + + @Test + public void attemptArchiveCheckedOutService() { + checkoutComponent(serviceVertex); + archiveComponent(serviceVertex.getUniqueId(), HttpStatus.CONFLICT.value()); + } + + @Test + public void testOnArchivedVsps(){ + String path = "/v1/catalog/notif/vsp/archived"; + List<String> csarIds = new LinkedList<>(); + csarIds.add("123456"); + csarIds.add(CSAR_UUID2); //An archived CSAR ID + Response response = target() + .path(path) + .request(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, designerUser.getUserId()) + .post(Entity.json(csarIds)); + + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); + assertOnVertexProp(resourceVertexVspArchived.getUniqueId(), true); + } + + @Test + public void testOnRestoredVsps(){ + String path = "/v1/catalog/notif/vsp/restored"; + List<String> csarIds = new LinkedList<>(); + csarIds.add("123456"); + csarIds.add(CSAR_UUID1); //Non archived CSAR_ID + Response response = target() + .path(path) + .request(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, designerUser.getUserId()) + .post(Entity.json(csarIds)); + + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); + assertOnVertexProp(resourceVertex.getUniqueId(), false); + } + + /* + * Rainy Scenarios + */ + @Test + public void archiveWithInvalidUid() { + archiveComponent("fakeUid", HttpStatus.NOT_FOUND.value()); + } + + @Test + public void restoreWithInvalidUid() { + restoreComponent("fakeUid", HttpStatus.NOT_FOUND.value()); + } + + @Test + public void archiveWithTester() { + String path = String.format("/v1/catalog/services/%s/%s", serviceVertex.getUniqueId(), "archive"); + Response response = target() + .path(path) + .request() + .accept(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, otherUser.getUserId()) + .post(null); + + assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED.value()); + } + + private void checkoutComponent(GraphVertex component) { + Either<GraphVertex, TitanOperationStatus> vE = titanDao.getVertexById(component.getUniqueId()); + GraphVertex v = vE.left().value(); + v.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + v.setJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + titanDao.updateVertex(v); + titanDao.commit(); + } + + private void assertOnVertexProp(String componentId, Object expectedValue) { + Either<GraphVertex, TitanOperationStatus> vE = titanDao.getVertexById(componentId); + GraphVertex v = vE.left().value(); + assertThat(v.getMetadataProperty(GraphPropertyEnum.IS_VSP_ARCHIVED)).isEqualTo(expectedValue); + } + + private void archiveComponent(String id, int expectedStatus){ archiveOrRestoreComponent(id, ArchiveOperation.Action.ARCHIVE, expectedStatus); } + private void restoreComponent(String id, int expectedStatus){ archiveOrRestoreComponent(id, ArchiveOperation.Action.RESTORE, expectedStatus); } + + private void archiveOrRestoreComponent(String compUid, ArchiveOperation.Action action, int expectedStatus) { + String path = String.format("/v1/catalog/services/%s/%s", compUid, action.name().toLowerCase()); + Response response = target() + .path(path) + .request() + .accept(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, designerUser.getUserId()) + .post(null); + + assertThat(response.getStatus()).isEqualTo(expectedStatus); + } + + private void assertOnGetArchivedComponents(String componentType, int expectedCount) { + String path = "/v1/catalog/archive"; + + Response response = target() + .path(path) + .request() + .accept(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, designerUser.getUserId()) + .get(); + + Map<String, List<CatalogComponent>> archivedComponents = response.readEntity(new GenericType<Map<String, List<CatalogComponent>>>() { }); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); + + if (componentType == null) { + assertThat(archivedComponents).isEmpty(); + } else { + assertThat(archivedComponents.get(componentType)).hasSize(expectedCount); + } + + } + + @Override + protected Application configure() { + ApplicationContext context = new AnnotationConfigApplicationContext(TestSpringConfig.class); + return new ResourceConfig(ArchiveEndpoint.class) + .register(DefaultExceptionMapper.class) + .register(ComponentExceptionMapper.class) + .register(StorageExceptionMapper.class) + .property("contextConfig", context); + } +} |