b6b1dc5cd933f7ecb37138b36ceac001b28eb2ef
[sdc.git] / catalog-be / src / test / java / org / openecomp / sdc / be / servlets / ComponentSubstitutionFilterServletTest.java
1 /*
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
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
20 package org.openecomp.sdc.be.servlets;
21
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.anyString;
27 import static org.mockito.ArgumentMatchers.nullable;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.reset;
30 import static org.mockito.Mockito.times;
31 import static org.mockito.Mockito.verify;
32 import static org.mockito.Mockito.when;
33 import static org.openecomp.sdc.common.api.Constants.USER_ID_HEADER;
34
35 import com.fasterxml.jackson.core.JsonProcessingException;
36 import com.fasterxml.jackson.databind.ObjectMapper;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.LinkedList;
40 import java.util.Optional;
41 import javax.servlet.ServletContext;
42 import javax.servlet.http.HttpServletRequest;
43 import javax.servlet.http.HttpSession;
44 import javax.ws.rs.client.Entity;
45 import javax.ws.rs.core.MediaType;
46 import javax.ws.rs.core.Response;
47 import org.eclipse.jetty.http.HttpStatus;
48 import org.glassfish.hk2.utilities.binding.AbstractBinder;
49 import org.glassfish.jersey.server.ResourceConfig;
50 import org.glassfish.jersey.test.JerseyTest;
51 import org.glassfish.jersey.test.TestProperties;
52 import org.junit.jupiter.api.AfterEach;
53 import org.junit.jupiter.api.BeforeAll;
54 import org.junit.jupiter.api.BeforeEach;
55 import org.junit.jupiter.api.Test;
56 import org.mockito.ArgumentMatchers;
57 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
58 import org.openecomp.sdc.be.components.impl.ComponentSubstitutionFilterBusinessLogic;
59 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
60 import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
61 import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction;
62 import org.openecomp.sdc.be.components.validation.UserValidations;
63 import org.openecomp.sdc.be.config.SpringConfig;
64 import org.openecomp.sdc.be.dao.api.ActionStatus;
65 import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor;
66 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
67 import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
68 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
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.ui.model.UIConstraint;
75 import org.openecomp.sdc.be.user.Role;
76 import org.openecomp.sdc.be.user.UserBusinessLogic;
77 import org.openecomp.sdc.common.api.Constants;
78 import org.openecomp.sdc.exception.ResponseFormat;
79 import org.springframework.context.ApplicationContext;
80 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
81 import org.springframework.web.context.WebApplicationContext;
82
83 public class ComponentSubstitutionFilterServletTest extends JerseyTest {
84
85     private static final String USER_ID = "jh0003";
86     private static final String servicePropertyName = "controller_actor";
87     private static final String constraintOperator = "equal";
88     private static final String sourceType = "static";
89     private static final String sourceName = sourceType;
90     private static final String propertyValue = "constraintValue";
91     private static final String componentId = "dac65869-dfb4-40d2-aa20-084324659ec1";
92     private static final String componentInstance = "dac65869-dfb4-40d2-aa20-084324659ec1.service0";
93     private static final String componentType = "services";
94
95     private static HttpServletRequest request;
96     private static HttpSession session;
97     private static ServletContext servletContext;
98     private static WebAppContextWrapper webAppContextWrapper;
99     private static WebApplicationContext webApplicationContext;
100     private static UserBusinessLogic userBusinessLogic;
101     private static ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
102     private static ComponentsUtils componentsUtils;
103     private static ServletUtils servletUtils;
104     private static ResourceImportManager resourceImportManager;
105     private static ComponentSubstitutionFilterBusinessLogic componentSubstitutionFilterBusinessLogic;
106     private static ResponseFormat responseFormat;
107     private static UserValidations userValidations;
108
109     private SubstitutionFilterDataDefinition substitutionFilterDataDefinition;
110     private RequirementSubstitutionFilterPropertyDataDefinition requirementSubstitutionFilterPropertyDataDefinition;
111     private UIConstraint uiConstraint;
112     private String constraint;
113     private String inputJson;
114     private User user;
115
116     @BeforeAll
117     public static void initClass() {
118         createMocks();
119         when(request.getSession()).thenReturn(session);
120         when(session.getServletContext()).thenReturn(servletContext);
121         when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR))
122             .thenReturn(webAppContextWrapper);
123         when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext);
124         when(webApplicationContext.getBean(ComponentSubstitutionFilterBusinessLogic.class))
125             .thenReturn(componentSubstitutionFilterBusinessLogic);
126         when(request.getHeader("USER_ID")).thenReturn(USER_ID);
127         when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
128         when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils);
129     }
130
131     @BeforeEach
132     public void resetMock() throws Exception {
133         super.setUp();
134         reset(componentSubstitutionFilterBusinessLogic);
135         initComponentData();
136     }
137
138     @AfterEach
139     void after() throws Exception {
140         super.tearDown();
141     }
142
143     @Test
144     public void addSubstitutionFilterTest() throws BusinessLogicException {
145         final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/substitutionFilter";
146         final String path = String.format(pathFormat, componentType, componentId, componentInstance);
147
148         when(userValidations.validateUserExists(user)).thenReturn(user);
149         when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
150         when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
151         when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
152
153         assertNotNull(uiConstraint);
154         assertThat(servicePropertyName).isEqualToIgnoringCase(uiConstraint.getServicePropertyName());
155         assertThat(constraintOperator).isEqualToIgnoringCase(uiConstraint.getConstraintOperator());
156         assertThat(sourceType).isEqualToIgnoringCase(uiConstraint.getSourceType());
157         assertThat(sourceName).isEqualToIgnoringCase(uiConstraint.getSourceName());
158         assertThat(propertyValue).isEqualToIgnoringCase(uiConstraint.getValue().toString());
159
160         when(componentsUtils.parseToConstraint(anyString(), any(User.class), any(ComponentTypeEnum.class)))
161             .thenReturn(Optional.of(uiConstraint));
162
163         assertNotNull(constraint);
164         assertNotNull(substitutionFilterDataDefinition);
165         assertThat(substitutionFilterDataDefinition.getProperties().getListToscaDataDefinition()).hasSize(1);
166         assertThat("controller_actor: {equal: constraintValue}\n").isEqualToIgnoringCase(constraint);
167
168         when(componentSubstitutionFilterBusinessLogic.createSubstitutionFilterIfNotExist(componentId,
169             componentInstance, true, ComponentTypeEnum.SERVICE))
170             .thenReturn(Optional.ofNullable(substitutionFilterDataDefinition));
171
172         when(componentSubstitutionFilterBusinessLogic
173             .addSubstitutionFilter(componentId, componentInstance, NodeFilterConstraintAction.ADD,
174                 uiConstraint.getServicePropertyName(), constraint, true, ComponentTypeEnum.SERVICE))
175             .thenReturn(Optional.ofNullable(substitutionFilterDataDefinition));
176
177         final Response response = target()
178             .path(path)
179             .request(MediaType.APPLICATION_JSON)
180             .header(USER_ID_HEADER, USER_ID)
181             .post(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
182
183         assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200);
184
185         verify(componentSubstitutionFilterBusinessLogic, times(1))
186             .createSubstitutionFilterIfNotExist(componentId, componentInstance, true, ComponentTypeEnum.SERVICE);
187
188         verify(componentSubstitutionFilterBusinessLogic, times(1))
189             .addSubstitutionFilter(anyString(), anyString(), any(NodeFilterConstraintAction.class), anyString(),
190                 anyString(), anyBoolean(), any(ComponentTypeEnum.class));
191     }
192
193     @Test
194     public void addSubstitutionFilterFailConstraintParseTest() {
195         final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/substitutionFilter";
196         final String path = String.format(pathFormat, componentType, componentId, componentInstance);
197
198         when(userValidations.validateUserExists(user)).thenReturn(user);
199         when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
200         when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
201
202         when(componentsUtils.parseToConstraint(anyString(), any(User.class), nullable(ComponentTypeEnum.class)))
203             .thenReturn(Optional.empty());
204
205         final Response response = target()
206             .path(path)
207             .request(MediaType.APPLICATION_JSON)
208             .header(USER_ID_HEADER, USER_ID)
209             .post(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
210
211         assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
212     }
213
214     @Test
215     public void addSubstitutionFilterFailTest() throws BusinessLogicException {
216         final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/substitutionFilter";
217         final String path = String.format(pathFormat, componentType, componentId, componentInstance);
218
219         when(userValidations.validateUserExists(user)).thenReturn(user);
220         when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
221         when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
222
223         when(componentsUtils.parseToConstraint(anyString(), any(User.class), any(ComponentTypeEnum.class)))
224             .thenReturn(Optional.of(uiConstraint));
225
226         when(componentSubstitutionFilterBusinessLogic.createSubstitutionFilterIfNotExist(componentId,
227             componentInstance, true, ComponentTypeEnum.SERVICE))
228             .thenReturn(Optional.empty());
229
230         final Response response = target()
231             .path(path)
232             .request(MediaType.APPLICATION_JSON)
233             .header(USER_ID_HEADER, USER_ID)
234             .post(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
235
236         assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
237
238         verify(componentSubstitutionFilterBusinessLogic, times(1))
239             .createSubstitutionFilterIfNotExist(componentId, componentInstance, true, ComponentTypeEnum.SERVICE);
240     }
241
242     @Test
243     public void updateSubstitutionFilterTest() throws BusinessLogicException {
244         final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/substitutionFilter";
245         final String path = String.format(pathFormat, componentType, componentId, componentInstance);
246
247         when(userValidations.validateUserExists(user)).thenReturn(user);
248         when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
249         when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
250         when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
251
252         when(componentsUtils.validateAndParseConstraint(ArgumentMatchers.any(ComponentTypeEnum.class), anyString(),
253             any(User.class))).thenReturn(Collections.singletonList(uiConstraint));
254
255         when(componentSubstitutionFilterBusinessLogic.updateSubstitutionFilter(componentId.toLowerCase(),
256             componentInstance, Collections.singletonList(constraint), true, ComponentTypeEnum.SERVICE))
257             .thenReturn(Optional.ofNullable(substitutionFilterDataDefinition));
258
259         final Response response = target()
260             .path(path)
261             .request(MediaType.APPLICATION_JSON)
262             .header(USER_ID_HEADER, USER_ID)
263             .put(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
264
265         assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200);
266
267         verify(componentSubstitutionFilterBusinessLogic, times(1))
268             .updateSubstitutionFilter(componentId.toLowerCase(), componentInstance,
269                 Collections.singletonList(constraint), true, ComponentTypeEnum.SERVICE);
270     }
271
272     @Test
273     public void updateSubstitutionFilterFailConstraintParseTest() {
274         final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/substitutionFilter";
275         final String path = String.format(pathFormat, componentType, componentId, componentInstance);
276
277         when(userValidations.validateUserExists(user)).thenReturn(user);
278         when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
279         when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
280
281         when(componentsUtils.validateAndParseConstraint(ArgumentMatchers.any(ComponentTypeEnum.class), anyString(),
282             any(User.class))).thenReturn(Collections.emptyList());
283
284         final Response response = target()
285             .path(path)
286             .request(MediaType.APPLICATION_JSON)
287             .header(USER_ID_HEADER, USER_ID)
288             .put(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
289
290         assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
291     }
292
293     @Test
294     public void updateSubstitutionFilterFailTest() throws BusinessLogicException {
295         final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/substitutionFilter";
296         final String path = String.format(pathFormat, componentType, componentId, componentInstance);
297
298         when(userValidations.validateUserExists(user)).thenReturn(user);
299         when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
300         when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
301
302         when(componentsUtils.validateAndParseConstraint(ArgumentMatchers.any(ComponentTypeEnum.class), anyString(),
303             any(User.class))).thenReturn(Collections.singletonList(uiConstraint));
304
305         when(componentSubstitutionFilterBusinessLogic.updateSubstitutionFilter(componentId.toLowerCase(),
306             componentInstance, Collections.singletonList(constraint), true, ComponentTypeEnum.SERVICE))
307             .thenReturn(Optional.empty());
308
309         final Response response = target()
310             .path(path)
311             .request(MediaType.APPLICATION_JSON)
312             .header(USER_ID_HEADER, USER_ID)
313             .put(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
314
315         assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
316
317         verify(componentSubstitutionFilterBusinessLogic, times(1))
318             .updateSubstitutionFilter(componentId.toLowerCase(), componentInstance,
319                 Collections.singletonList(constraint), true, ComponentTypeEnum.SERVICE);
320     }
321
322     @Test
323     public void deleteSubstitutionFilterConstraintTest() throws BusinessLogicException {
324         final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/substitutionFilter/0";
325         final String path = String.format(pathFormat, componentType, componentId, componentInstance);
326
327         when(userValidations.validateUserExists(user)).thenReturn(user);
328         when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
329         when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
330         when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
331
332         when(componentSubstitutionFilterBusinessLogic.deleteSubstitutionFilter(componentId, componentInstance,
333             NodeFilterConstraintAction.DELETE, null, 0, true, ComponentTypeEnum.SERVICE))
334             .thenReturn(Optional.ofNullable(substitutionFilterDataDefinition));
335
336         final Response response = target()
337             .path(path)
338             .request(MediaType.APPLICATION_JSON)
339             .header(USER_ID_HEADER, USER_ID)
340             .delete(Response.class);
341
342         assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200);
343
344         verify(componentSubstitutionFilterBusinessLogic, times(1))
345             .deleteSubstitutionFilter(componentId, componentInstance,
346                 NodeFilterConstraintAction.DELETE, null, 0, true, ComponentTypeEnum.SERVICE);
347     }
348
349     @Test
350     public void deleteSubstitutionFilterConstraintFailTest() throws BusinessLogicException {
351         final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/substitutionFilter/0";
352         final String path = String.format(pathFormat, componentType, componentId, componentInstance);
353
354         when(userValidations.validateUserExists(user)).thenReturn(user);
355         when(componentSubstitutionFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
356         when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
357
358         when(componentSubstitutionFilterBusinessLogic.deleteSubstitutionFilter(componentId, componentInstance,
359             NodeFilterConstraintAction.DELETE, null, 0, true, ComponentTypeEnum.SERVICE))
360             .thenReturn(Optional.empty());
361
362         final Response response = target()
363             .path(path)
364             .request(MediaType.APPLICATION_JSON)
365             .header(USER_ID_HEADER, USER_ID)
366             .delete(Response.class);
367
368         assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
369
370         verify(componentSubstitutionFilterBusinessLogic, times(1))
371             .deleteSubstitutionFilter(componentId, componentInstance,
372                 NodeFilterConstraintAction.DELETE, null, 0, true, ComponentTypeEnum.SERVICE);
373
374     }
375
376     private static void createMocks() {
377         request = mock(HttpServletRequest.class);
378         userBusinessLogic = mock(UserBusinessLogic.class);
379         componentInstanceBusinessLogic = mock(ComponentInstanceBusinessLogic.class);
380         componentsUtils = mock(ComponentsUtils.class);
381         servletUtils = mock(ServletUtils.class);
382         resourceImportManager = mock(ResourceImportManager.class);
383         componentSubstitutionFilterBusinessLogic = mock(ComponentSubstitutionFilterBusinessLogic.class);
384
385         session = mock(HttpSession.class);
386         servletContext = mock(ServletContext.class);
387         webAppContextWrapper = mock(WebAppContextWrapper.class);
388         webApplicationContext = mock(WebApplicationContext.class);
389         responseFormat = mock(ResponseFormat.class);
390         userValidations = mock(UserValidations.class);
391     }
392
393     @Override
394     protected ResourceConfig configure() {
395         forceSet(TestProperties.CONTAINER_PORT, "0");
396         final ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
397         return new ResourceConfig(ComponentSubstitutionFilterServlet.class)
398             .register(new AbstractBinder() {
399                 @Override
400                 protected void configure() {
401                     bind(request).to(HttpServletRequest.class);
402                     bind(userBusinessLogic).to(UserBusinessLogic.class);
403                     bind(componentInstanceBusinessLogic).to(ComponentInstanceBusinessLogic.class);
404                     bind(componentsUtils).to(ComponentsUtils.class);
405                     bind(servletUtils).to(ServletUtils.class);
406                     bind(resourceImportManager).to(ResourceImportManager.class);
407                     bind(componentSubstitutionFilterBusinessLogic).to(ComponentSubstitutionFilterBusinessLogic.class);
408                 }
409             })
410             .property("contextConfig", context);
411     }
412
413     private void initComponentData() throws JsonProcessingException {
414         uiConstraint = new UIConstraint(servicePropertyName, constraintOperator, sourceType, sourceName, propertyValue);
415         constraint = new ConstraintConvertor().convert(uiConstraint);
416         inputJson = buildConstraintDataJson(uiConstraint);
417
418         requirementSubstitutionFilterPropertyDataDefinition = new RequirementSubstitutionFilterPropertyDataDefinition();
419         requirementSubstitutionFilterPropertyDataDefinition.setName(uiConstraint.getServicePropertyName());
420         requirementSubstitutionFilterPropertyDataDefinition.setConstraints(new LinkedList<>(Arrays.asList(constraint)));
421
422         final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> listDataDefinition =
423             new ListDataDefinition<>(
424                 new LinkedList<>(Arrays.asList(requirementSubstitutionFilterPropertyDataDefinition)));
425
426         substitutionFilterDataDefinition = new SubstitutionFilterDataDefinition();
427         substitutionFilterDataDefinition.setProperties(listDataDefinition);
428         substitutionFilterDataDefinition.setID("SUBSTITUTION_FILTER_UID");
429
430         user = new User();
431         user.setUserId(USER_ID);
432         user.setRole(Role.ADMIN.name());
433     }
434
435     private String buildConstraintDataJson(final UIConstraint uiConstraint) throws JsonProcessingException {
436         final ObjectMapper mapper = new ObjectMapper();
437         return mapper.writeValueAsString(uiConstraint);
438     }
439
440 }