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
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.
16 * SPDX-License-Identifier: Apache-2.0
17 * ============LICENSE_END=========================================================
19 package org.openecomp.sdc.be.servlets;
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;
27 import com.fasterxml.jackson.core.JsonProcessingException;
28 import com.fasterxml.jackson.databind.ObjectMapper;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.nio.file.Path;
32 import java.util.List;
33 import javax.servlet.ServletContext;
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpSession;
36 import javax.ws.rs.client.Entity;
37 import javax.ws.rs.core.HttpHeaders;
38 import javax.ws.rs.core.MediaType;
39 import javax.ws.rs.core.Response.Status;
40 import org.apache.commons.lang3.StringUtils;
41 import org.eclipse.jetty.http.HttpStatus;
42 import org.glassfish.hk2.utilities.binding.AbstractBinder;
43 import org.glassfish.jersey.client.ClientConfig;
44 import org.glassfish.jersey.media.multipart.FormDataMultiPart;
45 import org.glassfish.jersey.media.multipart.MultiPartFeature;
46 import org.glassfish.jersey.server.ResourceConfig;
47 import org.glassfish.jersey.test.JerseyTest;
48 import org.glassfish.jersey.test.TestProperties;
49 import org.junit.jupiter.api.AfterEach;
50 import org.junit.jupiter.api.BeforeEach;
51 import org.junit.jupiter.api.Test;
52 import org.mockito.Mock;
53 import org.mockito.MockitoAnnotations;
54 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
55 import org.openecomp.sdc.be.components.impl.ModelBusinessLogic;
56 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
57 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
58 import org.openecomp.sdc.be.components.validation.UserValidations;
59 import org.openecomp.sdc.be.config.ConfigurationManager;
60 import org.openecomp.sdc.be.config.SpringConfig;
61 import org.openecomp.sdc.be.dao.api.ActionStatus;
62 import org.openecomp.sdc.be.exception.BusinessException;
63 import org.openecomp.sdc.be.impl.ComponentsUtils;
64 import org.openecomp.sdc.be.impl.ServletUtils;
65 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
66 import org.openecomp.sdc.be.model.Model;
67 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
68 import org.openecomp.sdc.be.servlets.builder.ServletResponseBuilder;
69 import org.openecomp.sdc.be.servlets.exception.OperationExceptionMapper;
70 import org.openecomp.sdc.be.ui.model.ModelCreateRequest;
71 import org.openecomp.sdc.be.user.UserBusinessLogic;
72 import org.openecomp.sdc.common.api.ConfigurationSource;
73 import org.openecomp.sdc.common.api.Constants;
74 import org.openecomp.sdc.common.impl.ExternalConfiguration;
75 import org.openecomp.sdc.common.impl.FSConfigurationSource;
76 import org.openecomp.sdc.exception.ResponseFormat;
77 import org.springframework.context.ApplicationContext;
78 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
79 import org.springframework.web.context.WebApplicationContext;
81 class ModelServletTest extends JerseyTest {
83 private static final String USER_ID = "cs0008";
86 private HttpServletRequest request;
88 private HttpSession session;
90 private ServletContext servletContext;
92 private WebAppContextWrapper webAppContextWrapper;
94 private WebApplicationContext webApplicationContext;
96 private UserBusinessLogic userBusinessLogic;
98 private ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
100 private ComponentsUtils componentsUtils;
102 private ServletUtils servletUtils;
104 private ResourceImportManager resourceImportManager;
106 private ModelBusinessLogic modelBusinessLogic;
108 private ResponseFormat responseFormat;
110 private UserValidations userValidations;
113 private ResponseFormatManager responseFormatManager;
116 private ModelCreateRequest modelCreateRequest;
117 private final Path rootPath = Path.of("/v1/catalog/model");
118 private final Path importsPath = rootPath.resolve("imports");
121 void resetMock() throws Exception {
129 void after() throws Exception {
133 private void initMocks() {
134 when(request.getSession()).thenReturn(session);
135 when(session.getServletContext()).thenReturn(servletContext);
136 when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR))
137 .thenReturn(webAppContextWrapper);
138 when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext);
139 when(webApplicationContext.getBean(ModelBusinessLogic.class)).thenReturn(modelBusinessLogic);
140 when(request.getHeader(Constants.USER_ID_HEADER)).thenReturn(USER_ID);
141 when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
142 when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils);
145 private void initConfig() {
146 final String appConfigDir = "src/test/resources/config/catalog-be";
147 final ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
148 final ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
149 final org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration();
150 configuration.setJanusGraphInMemoryGraph(true);
151 configurationManager.setConfiguration(configuration);
152 ExternalConfiguration.setAppName("catalog-be");
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);
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() {
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);
181 .register(new OperationExceptionMapper(new ServletResponseBuilder(), responseFormatManager))
182 .register(MultiPartFeature.class)
183 .property("contextConfig", context);
187 protected void configureClient(final ClientConfig config) {
188 config.register(MultiPartFeature.class);
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());
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());
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());
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());
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() {});
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());
254 void updateModelImportsSuccessTest() {
255 final FormDataMultiPart formDataMultiPart = buildUpdateFormDataMultiPart("model1", new byte[0]);
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());
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());
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());
291 void listModelSuccessTest() throws IOException {
292 var model1 = new Model("model1");
293 var model2 = new Model("model2");
294 var model3 = new Model("model3");
295 final List<Model> modelList = List.of(model1, model2, model3);
296 when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
297 when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
298 when(modelBusinessLogic.listModels()).thenReturn(modelList);
300 final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
301 .header(Constants.USER_ID_HEADER, USER_ID)
304 assertEquals(Status.OK.getStatusCode(), response.getStatus());
305 assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
306 final String responseBody = response.readEntity(String.class);
307 final String toRepresentation = (String) RepresentationUtils.toRepresentation(modelList);
308 assertEquals(toRepresentation, responseBody);
312 void listModelErrorTest() {
313 when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
314 when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
315 doThrow(new RuntimeException()).when(modelBusinessLogic).listModels();
317 final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
318 .header(Constants.USER_ID_HEADER, USER_ID)
321 assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
324 private FormDataMultiPart buildUpdateFormDataMultiPart(final String modelName, final byte[] importFilesZip) {
325 return new FormDataMultiPart()
326 .field("modelName", modelName)
327 .field("modelImportsZip", importFilesZip, MediaType.MULTIPART_FORM_DATA_TYPE);
330 private FormDataMultiPart buildCreateFormDataMultiPart(final byte[] modelFile, final String modelCreateAsJson) {
331 return new FormDataMultiPart()
332 .field("model", modelCreateAsJson, MediaType.APPLICATION_JSON_TYPE)
333 .field("modelImportsZip", modelFile, MediaType.MULTIPART_FORM_DATA_TYPE);
336 private String parseToJsonString(final Object object) throws JsonProcessingException {
337 return new ObjectMapper().writeValueAsString(object);