Centralize TOSCA function validation
[sdc.git] / catalog-be / src / test / java / org / openecomp / sdc / be / servlets / GroupEndpointTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.servlets;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.mockito.ArgumentMatchers.any;
25 import static org.mockito.ArgumentMatchers.anyString;
26 import static org.mockito.ArgumentMatchers.eq;
27 import static org.mockito.ArgumentMatchers.isA;
28 import static org.mockito.Mockito.anyList;
29 import static org.mockito.Mockito.doNothing;
30 import static org.mockito.Mockito.mock;
31 import static org.mockito.Mockito.when;
32 import static org.openecomp.sdc.be.model.operations.api.StorageOperationStatus.NOT_FOUND;
33
34 import com.fasterxml.jackson.databind.DeserializationFeature;
35 import fj.data.Either;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.List;
40 import java.util.Optional;
41 import javax.ws.rs.client.Entity;
42 import javax.ws.rs.client.Invocation;
43 import javax.ws.rs.core.GenericType;
44 import javax.ws.rs.core.MediaType;
45 import javax.ws.rs.core.Response;
46 import org.assertj.core.api.AssertionsForClassTypes;
47 import org.glassfish.jersey.client.ClientConfig;
48 import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJaxbJsonProvider;
49 import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJsonProvider;
50 import org.glassfish.jersey.logging.LoggingFeature;
51 import org.glassfish.jersey.server.ResourceConfig;
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.invocation.InvocationOnMock;
58 import org.mockito.stubbing.Answer;
59 import org.openecomp.sdc.be.components.impl.GroupBusinessLogicNew;
60 import org.openecomp.sdc.be.components.validation.AccessValidations;
61 import org.openecomp.sdc.be.components.validation.ComponentValidations;
62 import org.openecomp.sdc.be.config.ConfigurationManager;
63 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
64 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
65 import org.openecomp.sdc.be.datatypes.enums.PromoteVersionEnum;
66 import org.openecomp.sdc.be.impl.ComponentsUtils;
67 import org.openecomp.sdc.be.model.Component;
68 import org.openecomp.sdc.be.model.ComponentInstance;
69 import org.openecomp.sdc.be.model.GroupDefinition;
70 import org.openecomp.sdc.be.model.GroupProperty;
71 import org.openecomp.sdc.be.model.Resource;
72 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.GroupsOperation;
73 import org.openecomp.sdc.be.model.operations.StorageException;
74 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
75 import org.openecomp.sdc.be.model.operations.impl.GroupOperation;
76 import org.openecomp.sdc.be.user.UserBusinessLogic;
77 import org.openecomp.sdc.common.api.ConfigurationSource;
78 import org.openecomp.sdc.common.api.Constants;
79 import org.openecomp.sdc.common.impl.ExternalConfiguration;
80 import org.openecomp.sdc.common.impl.FSConfigurationSource;
81 import org.springframework.context.annotation.Bean;
82 import org.springframework.context.annotation.Configuration;
83 import org.springframework.context.annotation.Import;
84 import org.springframework.http.HttpStatus;
85
86 class GroupEndpointTest extends JerseySpringBaseTest {
87
88     private static final String VALID_USER = "ab001";
89     private static final String INVALID_USER = "ab002";
90     private static final String VALID_COMPONENT_ID = "12345";
91     private static final String INVALID_COMPONENT_ID = "9999";
92     private static final String VALID_GROUP_ID = "1";
93     private static final String INVALID_GROUP_ID = "2";
94     public static final String A = "a";
95     private static final String VL1 = "VL1";
96     private static final String OLD_VALUE = "old value";
97     private static AccessValidations accessValidations;
98     private static ComponentValidations componentValidations;
99     private static GroupsOperation groupsOperation;
100     private static GroupOperation groupOperation;
101     private Resource cr;
102     private GroupDefinition g1;
103     private ComponentInstance ci;
104     private GroupProperty gp1;
105
106     @Configuration
107     @Import(BaseTestConfig.class)
108     static class GroupEndpointTestConfig {
109
110         @Bean
111         GroupEndpoint groupEndpoint() {
112             UserBusinessLogic userBusinessLogic = mock(UserBusinessLogic.class);
113             ComponentsUtils componentsUtils = mock(ComponentsUtils.class);
114
115             return new GroupEndpoint(userBusinessLogic, componentsUtils, groupBusinessLogic());
116         }
117
118         @Bean
119         GroupBusinessLogicNew groupBusinessLogic() {
120             return new GroupBusinessLogicNew(accessValidations, componentValidations, groupsOperation, groupOperation);
121         }
122     }
123
124     @BeforeAll
125     public static void initClass() {
126         ExternalConfiguration.setAppName("catalog-be");
127         String appConfigDir = "src/test/resources/config/catalog-be";
128         ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(),
129             appConfigDir);
130         ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
131         //ComponentsUtils needs configuration singleton to be set
132         componentValidations = mock(ComponentValidations.class);
133         accessValidations = mock(AccessValidations.class);
134         groupsOperation = mock(GroupsOperation.class);
135         groupOperation = mock(GroupOperation.class);
136
137     }
138
139     @Override
140     protected void configureClient(ClientConfig config) {
141         final JacksonJsonProvider jacksonJsonProvider = new JacksonJaxbJsonProvider()
142             .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
143         config.register(jacksonJsonProvider);
144     }
145
146     @Override
147     protected ResourceConfig configure() {
148         forceSet(TestProperties.CONTAINER_PORT, "0");
149         return super.configure(GroupEndpointTestConfig.class)
150             .register(GroupEndpoint.class)
151             .property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, "WARNING");
152     }
153
154     @BeforeEach
155     public void before() throws Exception {
156         super.setUp();
157         cr = new Resource();
158         cr.setSystemName("CR1");
159         g1 = new GroupDefinition();
160         g1.setUniqueId(VALID_GROUP_ID);
161         gp1 = new GroupProperty();
162         gp1.setUniqueId("1");
163         gp1.setName("p1");
164         gp1.setValue(OLD_VALUE);
165         g1.setProperties(Arrays.asList(gp1));
166         cr.setGroups(Arrays.asList(g1));
167         ci = new ComponentInstance();
168         ci.setUniqueId(A);
169         ci.setName(VL1);
170         happyScenarioSetup();
171         unhappyScenarioSetup();
172     }
173
174     @AfterEach
175     void after() throws Exception {
176         super.tearDown();
177     }
178
179     private void unhappyScenarioSetup() {
180         when(accessValidations
181             .validateUserCanWorkOnComponent(eq(INVALID_COMPONENT_ID), eq(ComponentTypeEnum.RESOURCE), eq(VALID_USER),
182                 anyString())).thenThrow(new StorageException(NOT_FOUND, INVALID_COMPONENT_ID));
183         when(componentValidations.getComponentInstance(cr, A)).thenReturn(Optional.of(ci));
184     }
185
186     private void happyScenarioSetup() {
187         when(accessValidations
188             .validateUserCanWorkOnComponent(eq(VALID_COMPONENT_ID), any(ComponentTypeEnum.class), eq(VALID_USER),
189                 anyString())).thenReturn(cr);
190         when(accessValidations
191             .validateUserCanRetrieveComponentData(eq(VALID_COMPONENT_ID), eq("resources"), eq(VALID_USER), anyString()))
192             .thenReturn(cr);
193         when(componentValidations.getComponentInstance(cr, A)).thenReturn(Optional.of(ci));
194         doNothing().when(groupsOperation)
195             .updateGroupOnComponent(eq(VALID_COMPONENT_ID), isA(GroupDefinition.class), any(PromoteVersionEnum.class));
196         when(groupOperation.validateAndUpdatePropertyValue(any(Component.class), isA(GroupProperty.class)))
197             .thenReturn(StorageOperationStatus.OK);
198         when(groupsOperation
199             .updateGroupPropertiesOnComponent(eq(VALID_COMPONENT_ID), isA(GroupDefinition.class), anyList(),
200                 any(PromoteVersionEnum.class))).thenAnswer((Answer<Either>) invocationOnMock -> {
201                     Object[] args = invocationOnMock.getArguments();
202                     return Either.left(Collections.singletonList(args[2]));
203                 });
204     }
205
206     @Test
207     void updateGroupMembers_success() {
208         List<String> ids = Arrays.asList(A);
209         List<String> updatedIds = buildUpdateGroupMembersCall(VALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
210             .post(Entity.entity(ids, MediaType.APPLICATION_JSON), new GenericType<List<String>>() {
211             });
212         assertThat(updatedIds.size()).isEqualTo(ids.size());
213         assertThat(updatedIds).containsExactlyInAnyOrder(ids.toArray(new String[ids.size()]));
214     }
215
216     @Test
217     void updateGroupMembersWith2IdenticalMembers_success() {
218         List<String> ids = Arrays.asList(A, A);
219         List<String> updatedIds = buildUpdateGroupMembersCall(VALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
220             .post(Entity.entity(ids, MediaType.APPLICATION_JSON), new GenericType<List<String>>() {
221             });
222         assertThat(updatedIds.size()).isEqualTo(1);
223         assertThat(updatedIds).containsExactlyInAnyOrder(String.valueOf(A));
224     }
225
226     @Test
227     void updateGroupMembersWithEmptyList_success() {
228         List<String> ids = new ArrayList<>();
229         List<String> updatedIds = buildUpdateGroupMembersCall(VALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
230             .post(Entity.entity(ids, MediaType.APPLICATION_JSON), new GenericType<List<String>>() {
231             });
232         assertThat(updatedIds.size()).isZero();
233     }
234
235     @Test
236     void updateGroupMember_InvalidComponentId_failure() {
237         List<String> ids = new ArrayList<>();
238         Response response = buildUpdateGroupMembersCall(INVALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
239             .post(Entity.entity(ids, MediaType.APPLICATION_JSON), Response.class);
240         AssertionsForClassTypes.assertThat(response.getStatus()).isEqualTo(HttpStatus.NOT_FOUND.value());
241     }
242
243     @Test
244     void updateGroupProperty_success() {
245         GroupProperty property = new GroupProperty();
246         property.setValue("value1");
247         property.setName("prop");
248         String propertyStr = "[{\"uniqueId\":\"1\",\"type\":null,\"required\":false,\"definition\":false,\"defaultValue\":null,\"description\":null,\"schema\":null,\"password\":false,\"name\":\"p1\",\"value\":\"new value\",\"label\":null,\"hidden\":false,\"immutable\":false,\"inputPath\":null,\"status\":null,\"inputId\":null,\"instanceUniqueId\":null,\"propertyId\":null,\"parentUniqueId\":null,\"getInputValues\":null,\"constraints\":null,\"valueUniqueUid\":null,\"ownerId\":null}]";
249         List<GroupProperty> properties = Arrays.asList(property);
250         //TODO define GroupPropertyDTO (after finding other usage in UI code) and improve test coverage
251 //        List<GroupProperty> updatedProperties = buildUpdateGroupPropertiesCall(VALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
252 //                .put(Entity.entity(propertyStr, MediaType.APPLICATION_JSON), new GenericType<List<GroupProperty>>() {
253 //                });
254 //        assertThat(updatedProperties.size()).isEqualTo(1);
255         Response response = buildUpdateGroupPropertiesCall(VALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
256             .put(Entity.entity(propertyStr, MediaType.APPLICATION_JSON));
257         assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
258     }
259
260     @Test
261     void getGroupProperties_success() {
262         List<PropertyDataDefinition> properties = buildUpdateGroupPropertiesCall(VALID_COMPONENT_ID, VALID_GROUP_ID,
263             VALID_USER)
264             .get(new GenericType<List<PropertyDataDefinition>>() {
265             });
266         assertThat(properties.size()).isEqualTo(1);
267         assertThat(properties.get(0).getValue()).isEqualTo(OLD_VALUE);
268     }
269
270     private Invocation.Builder buildUpdateGroupMembersCall(String componentId, String groupId, String userId) {
271         return target("/v1/catalog/resources/" + componentId + "/groups/" + groupId + "/members")
272             .request(MediaType.APPLICATION_JSON)
273             .accept(MediaType.APPLICATION_JSON)
274             .header(Constants.USER_ID_HEADER, userId);
275     }
276
277     private Invocation.Builder buildUpdateGroupPropertiesCall(String componentId, String groupId, String userId) {
278         return target("/v1/catalog/resources/" + componentId + "/groups/" + groupId + "/properties")
279             .request(MediaType.APPLICATION_JSON)
280             .accept(MediaType.APPLICATION_JSON)
281             .header(Constants.USER_ID_HEADER, userId);
282     }
283
284
285 }