2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2020 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=========================================================
20 package org.openecomp.sdc.be.servlets;
22 import static org.assertj.core.api.Assertions.assertThat;
23 import static org.junit.jupiter.api.Assertions.assertNotNull;
24 import static org.mockito.ArgumentMatchers.any;
25 import static org.mockito.ArgumentMatchers.anyBoolean;
26 import static org.mockito.ArgumentMatchers.anyInt;
27 import static org.mockito.ArgumentMatchers.anyList;
28 import static org.mockito.ArgumentMatchers.anyString;
29 import static org.mockito.ArgumentMatchers.nullable;
30 import static org.mockito.Mockito.mock;
31 import static org.mockito.Mockito.reset;
32 import static org.mockito.Mockito.times;
33 import static org.mockito.Mockito.verify;
34 import static org.mockito.Mockito.when;
35 import static org.openecomp.sdc.common.api.Constants.USER_ID_HEADER;
37 import com.fasterxml.jackson.core.JsonProcessingException;
38 import com.fasterxml.jackson.databind.ObjectMapper;
39 import java.util.Collections;
40 import java.util.List;
41 import java.util.Optional;
42 import javax.servlet.ServletContext;
43 import javax.servlet.http.HttpServletRequest;
44 import javax.servlet.http.HttpSession;
45 import javax.ws.rs.client.Entity;
46 import javax.ws.rs.core.MediaType;
47 import javax.ws.rs.core.Response;
48 import org.eclipse.jetty.http.HttpStatus;
49 import org.glassfish.hk2.utilities.binding.AbstractBinder;
50 import org.glassfish.jersey.server.ResourceConfig;
51 import org.glassfish.jersey.test.JerseyTest;
52 import org.glassfish.jersey.test.TestProperties;
53 import org.junit.jupiter.api.AfterEach;
54 import org.junit.jupiter.api.BeforeAll;
55 import org.junit.jupiter.api.BeforeEach;
56 import org.junit.jupiter.api.Test;
57 import org.mockito.ArgumentMatchers;
58 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
59 import org.openecomp.sdc.be.components.impl.ComponentSubstitutionFilterBusinessLogic;
60 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
61 import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
62 import org.openecomp.sdc.be.components.validation.UserValidations;
63 import org.openecomp.sdc.be.config.ConfigurationManager;
64 import org.openecomp.sdc.be.config.SpringConfig;
65 import org.openecomp.sdc.be.dao.api.ActionStatus;
66 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
67 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
68 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition;
69 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
70 import org.openecomp.sdc.be.impl.ComponentsUtils;
71 import org.openecomp.sdc.be.impl.ServletUtils;
72 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
73 import org.openecomp.sdc.be.model.User;
74 import org.openecomp.sdc.be.model.dto.FilterConstraintDto;
75 import org.openecomp.sdc.be.ui.mapper.FilterConstraintMapper;
76 import org.openecomp.sdc.be.ui.model.UIConstraint;
77 import org.openecomp.sdc.be.user.Role;
78 import org.openecomp.sdc.be.user.UserBusinessLogic;
79 import org.openecomp.sdc.common.api.ConfigurationSource;
80 import org.openecomp.sdc.common.api.Constants;
81 import org.openecomp.sdc.common.impl.ExternalConfiguration;
82 import org.openecomp.sdc.common.impl.FSConfigurationSource;
83 import org.openecomp.sdc.exception.ResponseFormat;
84 import org.springframework.context.ApplicationContext;
85 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
86 import org.springframework.web.context.WebApplicationContext;
88 public class ComponentSubstitutionFilterServletTest extends JerseyTest {
90 private static final String USER_ID = "jh0003";
91 private static final String servicePropertyName = "controller_actor";
92 private static final String constraintOperator = "equal";
93 private static final String sourceType = "static";
94 private static final String sourceName = sourceType;
95 private static final String propertyValue = "constraintValue";
96 private static final String componentId = "dac65869-dfb4-40d2-aa20-084324659ec1";
97 private static final String constraintType = "properties";
98 private static final String componentType = "services";
100 private static HttpServletRequest request;
101 private static HttpSession session;
102 private static ServletContext servletContext;
103 private static WebAppContextWrapper webAppContextWrapper;
104 private static WebApplicationContext webApplicationContext;
105 private static UserBusinessLogic userBusinessLogic;
106 private static ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
107 private static ComponentsUtils componentsUtils;
108 private static ServletUtils servletUtils;
109 private static ResourceImportManager resourceImportManager;
110 private static ComponentSubstitutionFilterBusinessLogic componentSubstitutionFilterBusinessLogic;
111 private static ResponseFormat responseFormat;
112 private static UserValidations userValidations;
113 private SubstitutionFilterDataDefinition substitutionFilterDataDefinition;
114 private UIConstraint uiConstraint;
115 private String inputJson;
117 private FilterConstraintDto filterConstraintDto;
120 public static void initClass() {
122 when(request.getSession()).thenReturn(session);
123 when(session.getServletContext()).thenReturn(servletContext);
124 when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR))
125 .thenReturn(webAppContextWrapper);
126 when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext);
127 when(webApplicationContext.getBean(ComponentSubstitutionFilterBusinessLogic.class))
128 .thenReturn(componentSubstitutionFilterBusinessLogic);
129 when(request.getHeader("USER_ID")).thenReturn(USER_ID);
130 when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
131 when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils);
132 String appConfigDir = "src/test/resources/config/catalog-be";
133 ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
134 ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
135 org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration();
136 configuration.setJanusGraphInMemoryGraph(true);
137 configurationManager.setConfiguration(configuration);
138 ExternalConfiguration.setAppName("catalog-be");
142 public void resetMock() throws Exception {
144 reset(componentSubstitutionFilterBusinessLogic);
149 void after() throws Exception {
154 void addSubstitutionFilterTest() throws Exception {
155 final String pathFormat = "/v1/catalog/%s/%s/substitutionFilter/%s";
156 final String path = String.format(pathFormat, componentType, componentId, constraintType);
158 when(userValidations.validateUserExists(user)).thenReturn(user);
159 when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
160 when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
161 when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
163 assertNotNull(uiConstraint);
164 assertThat(uiConstraint.getServicePropertyName()).isEqualToIgnoringCase(servicePropertyName);
165 assertThat(uiConstraint.getConstraintOperator()).isEqualToIgnoringCase(constraintOperator);
166 assertThat(uiConstraint.getSourceType()).isEqualToIgnoringCase(sourceType);
167 assertThat(uiConstraint.getSourceName()).isEqualToIgnoringCase(sourceName);
168 assertThat(uiConstraint.getValue().toString()).isEqualToIgnoringCase(propertyValue);
170 when(componentsUtils.parseToConstraint(anyString(), any(User.class), any(ComponentTypeEnum.class)))
171 .thenReturn(Optional.of(uiConstraint));
173 assertNotNull(substitutionFilterDataDefinition);
174 assertThat(substitutionFilterDataDefinition.getProperties().getListToscaDataDefinition()).hasSize(1);
175 when(componentSubstitutionFilterBusinessLogic.addSubstitutionFilter(componentId, filterConstraintDto, true, ComponentTypeEnum.SERVICE))
176 .thenReturn(Optional.of(substitutionFilterDataDefinition));
178 final Response response = target()
180 .request(MediaType.APPLICATION_JSON)
181 .header(USER_ID_HEADER, USER_ID)
182 .post(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
184 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200);
186 verify(componentSubstitutionFilterBusinessLogic, times(1))
187 .addSubstitutionFilter(componentId, filterConstraintDto, true, ComponentTypeEnum.SERVICE);
191 void addSubstitutionFilterFailConstraintParseTest() {
192 final String pathFormat = "/v1/catalog/%s/%s/substitutionFilter/%s";
193 final String path = String.format(pathFormat, componentType, componentId, constraintType);
195 when(userValidations.validateUserExists(user)).thenReturn(user);
196 when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
197 when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
199 when(componentsUtils.parseToConstraint(anyString(), any(User.class), nullable(ComponentTypeEnum.class)))
200 .thenReturn(Optional.empty());
202 final Response response = target()
204 .request(MediaType.APPLICATION_JSON)
205 .header(USER_ID_HEADER, USER_ID)
206 .post(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
208 assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
212 void addSubstitutionFilterFailTest() {
213 final String pathFormat = "/v1/catalog/%s/%s/substitutionFilter/%s";
214 final String path = String.format(pathFormat, componentType, componentId, constraintType);
216 when(userValidations.validateUserExists(user)).thenReturn(user);
217 when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
218 when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
220 when(componentsUtils.parseToConstraint(anyString(), any(User.class), any(ComponentTypeEnum.class)))
221 .thenReturn(Optional.of(uiConstraint));
223 final Response response = target()
225 .request(MediaType.APPLICATION_JSON)
226 .header(USER_ID_HEADER, USER_ID)
227 .post(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
229 assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
233 void updateSubstitutionFilterTest() throws BusinessLogicException {
234 final String pathFormat = "/v1/catalog/%s/%s/substitutionFilter/%s";
235 final String path = String.format(pathFormat, componentType, componentId, constraintType);
237 when(userValidations.validateUserExists(user)).thenReturn(user);
238 when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
239 when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
240 when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
242 when(componentsUtils.validateAndParseConstraint(ArgumentMatchers.any(ComponentTypeEnum.class), anyString(),
243 any(User.class))).thenReturn(Collections.singletonList(uiConstraint));
245 when(componentSubstitutionFilterBusinessLogic.updateSubstitutionFilter(componentId.toLowerCase(),
246 List.of(filterConstraintDto), true, ComponentTypeEnum.SERVICE))
247 .thenReturn(Optional.ofNullable(substitutionFilterDataDefinition));
249 final Response response = target()
251 .request(MediaType.APPLICATION_JSON)
252 .header(USER_ID_HEADER, USER_ID)
253 .put(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
255 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200);
257 verify(componentSubstitutionFilterBusinessLogic, times(1))
258 .updateSubstitutionFilter(anyString(), anyList(), anyBoolean(), any(ComponentTypeEnum.class));
262 void updateSubstitutionFilterFailConstraintParseTest() {
263 final String pathFormat = "/v1/catalog/%s/%s/substitutionFilter/%s";
264 final String path = String.format(pathFormat, componentType, componentId, constraintType);
266 when(userValidations.validateUserExists(user)).thenReturn(user);
267 when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
268 when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
270 when(componentsUtils.validateAndParseConstraint(ArgumentMatchers.any(ComponentTypeEnum.class), anyString(),
271 any(User.class))).thenReturn(Collections.emptyList());
273 final Response response = target()
275 .request(MediaType.APPLICATION_JSON)
276 .header(USER_ID_HEADER, USER_ID)
277 .put(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
279 assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
283 void updateSubstitutionFilterFailTest() {
284 final String pathFormat = "/v1/catalog/%s/%s/substitutionFilter/%s";
285 final String path = String.format(pathFormat, componentType, componentId, constraintType);
287 when(userValidations.validateUserExists(user)).thenReturn(user);
288 when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
289 when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
291 when(componentsUtils.validateAndParseConstraint(ArgumentMatchers.any(ComponentTypeEnum.class), anyString(),
292 any(User.class))).thenReturn(Collections.singletonList(uiConstraint));
294 final Response response = target()
296 .request(MediaType.APPLICATION_JSON)
297 .header(USER_ID_HEADER, USER_ID)
298 .put(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
300 assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
304 void deleteSubstitutionFilterConstraintTest() throws BusinessLogicException {
305 final String pathFormat = "/v1/catalog/%s/%s/substitutionFilter/%s/0";
306 final String path = String.format(pathFormat, componentType, componentId, constraintType);
308 when(userValidations.validateUserExists(user)).thenReturn(user);
309 when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
310 when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
311 when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
313 when(componentSubstitutionFilterBusinessLogic.deleteSubstitutionFilter(componentId, 0,
314 true, ComponentTypeEnum.SERVICE))
315 .thenReturn(Optional.ofNullable(substitutionFilterDataDefinition));
317 final Response response = target()
319 .request(MediaType.APPLICATION_JSON)
320 .header(USER_ID_HEADER, USER_ID)
321 .delete(Response.class);
323 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200);
325 verify(componentSubstitutionFilterBusinessLogic, times(1))
326 .deleteSubstitutionFilter(anyString(), anyInt(), anyBoolean(), any(ComponentTypeEnum.class));
330 void deleteSubstitutionFilterConstraintFailTest() {
331 final String pathFormat = "/v1/catalog/%s/%s/substitutionFilter/%s/0";
332 final String path = String.format(pathFormat, componentType, componentId, constraintType);
334 when(userValidations.validateUserExists(user)).thenReturn(user);
335 when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
336 when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
338 final Response response = target()
340 .request(MediaType.APPLICATION_JSON)
341 .header(USER_ID_HEADER, USER_ID)
342 .delete(Response.class);
344 assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
347 private static void createMocks() {
348 request = mock(HttpServletRequest.class);
349 userBusinessLogic = mock(UserBusinessLogic.class);
350 componentInstanceBusinessLogic = mock(ComponentInstanceBusinessLogic.class);
351 componentsUtils = mock(ComponentsUtils.class);
352 servletUtils = mock(ServletUtils.class);
353 resourceImportManager = mock(ResourceImportManager.class);
354 componentSubstitutionFilterBusinessLogic = mock(ComponentSubstitutionFilterBusinessLogic.class);
356 session = mock(HttpSession.class);
357 servletContext = mock(ServletContext.class);
358 webAppContextWrapper = mock(WebAppContextWrapper.class);
359 webApplicationContext = mock(WebApplicationContext.class);
360 responseFormat = mock(ResponseFormat.class);
361 userValidations = mock(UserValidations.class);
365 protected ResourceConfig configure() {
366 forceSet(TestProperties.CONTAINER_PORT, "0");
367 final ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
368 return new ResourceConfig(ComponentSubstitutionFilterServlet.class)
369 .register(new AbstractBinder() {
371 protected void configure() {
372 bind(request).to(HttpServletRequest.class);
373 bind(userBusinessLogic).to(UserBusinessLogic.class);
374 bind(componentInstanceBusinessLogic).to(ComponentInstanceBusinessLogic.class);
375 bind(componentsUtils).to(ComponentsUtils.class);
376 bind(servletUtils).to(ServletUtils.class);
377 bind(resourceImportManager).to(ResourceImportManager.class);
378 bind(componentSubstitutionFilterBusinessLogic).to(ComponentSubstitutionFilterBusinessLogic.class);
381 .property("contextConfig", context);
384 private void initComponentData() throws JsonProcessingException {
385 uiConstraint = new UIConstraint(servicePropertyName, constraintOperator, sourceType, sourceName, propertyValue);
386 final FilterConstraintMapper filterConstraintMapper = new FilterConstraintMapper();
387 filterConstraintDto = filterConstraintMapper.mapFrom(uiConstraint);
388 inputJson = buildConstraintDataJson(uiConstraint);
390 SubstitutionFilterPropertyDataDefinition substitutionFilterPropertyDataDefinition = new SubstitutionFilterPropertyDataDefinition();
391 substitutionFilterPropertyDataDefinition.setName(uiConstraint.getServicePropertyName());
392 substitutionFilterPropertyDataDefinition.setConstraints(List.of(filterConstraintMapper.mapTo(filterConstraintDto)));
394 final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> listDataDefinition =
395 new ListDataDefinition<>(List.of(substitutionFilterPropertyDataDefinition));
397 substitutionFilterDataDefinition = new SubstitutionFilterDataDefinition();
398 substitutionFilterDataDefinition.setProperties(listDataDefinition);
399 substitutionFilterDataDefinition.setID("SUBSTITUTION_FILTER_UID");
402 user.setUserId(USER_ID);
403 user.setRole(Role.ADMIN.name());
406 private String buildConstraintDataJson(final UIConstraint uiConstraint) throws JsonProcessingException {
407 final ObjectMapper mapper = new ObjectMapper();
408 return mapper.writeValueAsString(uiConstraint);