Add models imports endpoint and persistence structure
[sdc.git] / catalog-be / src / test / java / org / openecomp / sdc / be / servlets / ModelServletTest.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Nordix Foundation
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19 package org.openecomp.sdc.be.servlets;
20
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.ArgumentMatchers.eq;
24 import static org.mockito.Mockito.doThrow;
25 import static org.mockito.Mockito.when;
26
27 import com.fasterxml.jackson.core.JsonProcessingException;
28 import com.fasterxml.jackson.databind.ObjectMapper;
29 import java.io.InputStream;
30 import java.nio.file.Path;
31 import javax.servlet.ServletContext;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.servlet.http.HttpSession;
34 import javax.ws.rs.client.Entity;
35 import javax.ws.rs.core.MediaType;
36 import javax.ws.rs.core.Response.Status;
37 import org.apache.commons.lang3.StringUtils;
38 import org.eclipse.jetty.http.HttpStatus;
39 import org.glassfish.hk2.utilities.binding.AbstractBinder;
40 import org.glassfish.jersey.client.ClientConfig;
41 import org.glassfish.jersey.media.multipart.FormDataMultiPart;
42 import org.glassfish.jersey.media.multipart.MultiPartFeature;
43 import org.glassfish.jersey.server.ResourceConfig;
44 import org.glassfish.jersey.test.JerseyTest;
45 import org.glassfish.jersey.test.TestProperties;
46 import org.junit.jupiter.api.AfterEach;
47 import org.junit.jupiter.api.BeforeAll;
48 import org.junit.jupiter.api.BeforeEach;
49 import org.junit.jupiter.api.Test;
50 import org.junit.jupiter.api.TestInstance;
51 import org.junit.jupiter.api.TestInstance.Lifecycle;
52 import org.mockito.InjectMocks;
53 import org.mockito.Mock;
54 import org.mockito.MockitoAnnotations;
55 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
56 import org.openecomp.sdc.be.components.impl.ModelBusinessLogic;
57 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
58 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
59 import org.openecomp.sdc.be.components.validation.UserValidations;
60 import org.openecomp.sdc.be.config.ConfigurationManager;
61 import org.openecomp.sdc.be.config.SpringConfig;
62 import org.openecomp.sdc.be.dao.api.ActionStatus;
63 import org.openecomp.sdc.be.exception.BusinessException;
64 import org.openecomp.sdc.be.impl.ComponentsUtils;
65 import org.openecomp.sdc.be.impl.ServletUtils;
66 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
67 import org.openecomp.sdc.be.model.Model;
68 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
69 import org.openecomp.sdc.be.servlets.builder.ServletResponseBuilder;
70 import org.openecomp.sdc.be.servlets.exception.OperationExceptionMapper;
71 import org.openecomp.sdc.be.ui.model.ModelCreateRequest;
72 import org.openecomp.sdc.be.user.UserBusinessLogic;
73 import org.openecomp.sdc.common.api.ConfigurationSource;
74 import org.openecomp.sdc.common.api.Constants;
75 import org.openecomp.sdc.common.impl.ExternalConfiguration;
76 import org.openecomp.sdc.common.impl.FSConfigurationSource;
77 import org.openecomp.sdc.exception.ResponseFormat;
78 import org.springframework.context.ApplicationContext;
79 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
80 import org.springframework.web.context.WebApplicationContext;
81
82 @TestInstance(Lifecycle.PER_CLASS)
83 class ModelServletTest extends JerseyTest {
84
85     private static final String USER_ID = "cs0008";
86
87     @Mock
88     private HttpServletRequest request;
89     @Mock
90     private HttpSession session;
91     @Mock
92     private ServletContext servletContext;
93     @Mock
94     private WebAppContextWrapper webAppContextWrapper;
95     @Mock
96     private WebApplicationContext webApplicationContext;
97     @Mock
98     private UserBusinessLogic userBusinessLogic;
99     @Mock
100     private ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
101     @Mock
102     private ComponentsUtils componentsUtils;
103     @Mock
104     private ServletUtils servletUtils;
105     @Mock
106     private ResourceImportManager resourceImportManager;
107     @Mock
108     private ModelBusinessLogic modelBusinessLogic;
109     @InjectMocks
110     private ModelServlet modelServlet;
111     @Mock
112     private ResponseFormat responseFormat;
113     @Mock
114     private UserValidations userValidations;
115
116     @Mock
117     private ResponseFormatManager responseFormatManager;
118
119     private Model model;
120     private ModelCreateRequest modelCreateRequest;
121     private final Path rootPath = Path.of("/v1/catalog/model");
122     private final Path importsPath = rootPath.resolve("imports");
123
124     @BeforeAll
125     public void initClass() {
126         when(request.getSession()).thenReturn(session);
127         when(session.getServletContext()).thenReturn(servletContext);
128         when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR))
129             .thenReturn(webAppContextWrapper);
130         when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext);
131         when(webApplicationContext.getBean(ModelBusinessLogic.class)).thenReturn(modelBusinessLogic);
132         when(request.getHeader(Constants.USER_ID_HEADER)).thenReturn(USER_ID);
133         when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
134         when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils);
135         final String appConfigDir = "src/test/resources/config/catalog-be";
136         final ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
137         final ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
138         final org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration();
139         configuration.setJanusGraphInMemoryGraph(true);
140         configurationManager.setConfiguration(configuration);
141         ExternalConfiguration.setAppName("catalog-be");
142     }
143
144     @BeforeEach
145     void resetMock() throws Exception {
146         super.setUp();
147         initTestData();
148     }
149
150     @AfterEach
151     void after() throws Exception {
152         super.tearDown();
153     }
154
155     private void initTestData() {
156         final String modelName = "MY-INTEGRATION-TEST-MODEL";
157         model = new Model(modelName);
158         modelCreateRequest = new ModelCreateRequest();
159         modelCreateRequest.setName(modelName);
160     }
161
162     @Override
163     protected ResourceConfig configure() {
164         MockitoAnnotations.openMocks(this);
165         forceSet(TestProperties.CONTAINER_PORT, "0");
166         final ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
167         return new ResourceConfig(ModelServlet.class)
168             .register(new AbstractBinder() {
169                 @Override
170                 protected void configure() {
171                     bind(request).to(HttpServletRequest.class);
172                     bind(userBusinessLogic).to(UserBusinessLogic.class);
173                     bind(componentInstanceBusinessLogic).to(ComponentInstanceBusinessLogic.class);
174                     bind(componentsUtils).to(ComponentsUtils.class);
175                     bind(servletUtils).to(ServletUtils.class);
176                     bind(resourceImportManager).to(ResourceImportManager.class);
177                     bind(modelBusinessLogic).to(ModelBusinessLogic.class);
178                     bind(userValidations).to(UserValidations.class);
179                 }
180             })
181             .register(new OperationExceptionMapper(new ServletResponseBuilder(), responseFormatManager))
182             .register(MultiPartFeature.class)
183             .property("contextConfig", context);
184     }
185
186     @Override
187     protected void configureClient(final ClientConfig config) {
188         config.register(MultiPartFeature.class);
189     }
190
191     @Test
192     void createModelSuccessTest() throws JsonProcessingException {
193         when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
194         when(componentsUtils.getResponseFormat(ActionStatus.CREATED)).thenReturn(responseFormat);
195         when(modelBusinessLogic.createModel(any(Model.class))).thenReturn(model);
196         final FormDataMultiPart formDataMultiPart = buildCreateFormDataMultiPart(new byte[0], parseToJsonString(modelCreateRequest));
197         final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
198             .header(Constants.USER_ID_HEADER, USER_ID)
199             .post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
200         assertEquals(Status.OK.getStatusCode(), response.getStatus());
201     }
202
203     @Test
204     void createModelFailTest() throws JsonProcessingException {
205         when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
206         when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
207         when(modelBusinessLogic.createModel(any(Model.class))).thenReturn(model);
208         final FormDataMultiPart formDataMultiPart = buildCreateFormDataMultiPart(new byte[0], parseToJsonString(modelCreateRequest));
209         final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
210             .header(Constants.USER_ID_HEADER, USER_ID)
211             .post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
212         assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
213     }
214
215     @Test
216     void createModelFailWithModelNameEmptyTest() throws JsonProcessingException {
217         when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
218         when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
219         modelCreateRequest.setName(StringUtils.EMPTY);
220         final FormDataMultiPart formDataMultiPart = buildCreateFormDataMultiPart(new byte[0], parseToJsonString(modelCreateRequest));
221         final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
222             .header(Constants.USER_ID_HEADER, USER_ID)
223             .post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
224         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
225     }
226
227     @Test
228     void createModelFailWithModelNameNullTest() throws JsonProcessingException {
229         when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
230         when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
231         modelCreateRequest.setName(null);
232         final var modelFile = new byte[0];
233         final FormDataMultiPart formDataMultiPart = buildCreateFormDataMultiPart(modelFile, parseToJsonString(modelCreateRequest));
234         final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
235             .header(Constants.USER_ID_HEADER, USER_ID)
236             .post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
237         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
238     }
239
240     @Test
241     void createModelThrowsBusinessExceptionTest() throws JsonProcessingException {
242         final var modelFile = new byte[0];
243         final String modelCreateAsJson = parseToJsonString(modelCreateRequest);
244         final FormDataMultiPart formDataMultiPart = buildCreateFormDataMultiPart(modelFile, modelCreateAsJson);
245         when(modelBusinessLogic.createModel(model)).thenThrow(new BusinessException() {});
246
247         final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
248             .header(Constants.USER_ID_HEADER, USER_ID)
249             .post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
250         assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
251     }
252
253     @Test
254     void updateModelImportsSuccessTest() {
255         final FormDataMultiPart formDataMultiPart = buildUpdateFormDataMultiPart("model1", new byte[0]);
256
257         final var response = target(importsPath.toString()).request(MediaType.APPLICATION_JSON)
258             .header(Constants.USER_ID_HEADER, USER_ID)
259             .put(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
260         assertEquals(Status.NO_CONTENT.getStatusCode(), response.getStatus());
261     }
262
263     @Test
264     void updateModelImports_businessException() {
265         final var modelId = "model1";
266         final FormDataMultiPart formDataMultiPart = buildUpdateFormDataMultiPart(modelId, new byte[0]);
267         final OperationException operationException = new OperationException(ActionStatus.INVALID_MODEL, modelId);
268         doThrow(operationException).when(modelBusinessLogic).createModelImports(eq(modelId), any(InputStream.class));
269         when(responseFormatManager.getResponseFormat(ActionStatus.INVALID_MODEL, modelId))
270             .thenReturn(new ResponseFormat(Status.BAD_REQUEST.getStatusCode()));
271         final var response = target(importsPath.toString()).request(MediaType.APPLICATION_JSON)
272             .header(Constants.USER_ID_HEADER, USER_ID)
273             .put(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
274         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
275     }
276
277     @Test
278     void updateModelImports_unknownException() {
279         final var modelName = "model1";
280         final FormDataMultiPart formDataMultiPart = buildUpdateFormDataMultiPart(modelName, new byte[0]);
281         doThrow(new RuntimeException()).when(modelBusinessLogic).createModelImports(eq(modelName), any(InputStream.class));
282         when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
283         when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
284         final var response = target(importsPath.toString()).request(MediaType.APPLICATION_JSON)
285             .header(Constants.USER_ID_HEADER, USER_ID)
286             .put(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
287         assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
288     }
289
290     private FormDataMultiPart buildUpdateFormDataMultiPart(final String modelName, final byte[] importFilesZip) {
291         return new FormDataMultiPart()
292             .field("modelName", modelName)
293             .field("modelImportsZip", importFilesZip, MediaType.MULTIPART_FORM_DATA_TYPE);
294     }
295
296     private FormDataMultiPart buildCreateFormDataMultiPart(final byte[] modelFile, final String modelCreateAsJson) {
297         return new FormDataMultiPart()
298             .field("model", modelCreateAsJson, MediaType.APPLICATION_JSON_TYPE)
299             .field("modelImportsZip", modelFile, MediaType.MULTIPART_FORM_DATA_TYPE);
300     }
301
302     private String parseToJsonString(final Object object) throws JsonProcessingException {
303         return new ObjectMapper().writeValueAsString(object);
304     }
305
306 }