2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.be.servlets;
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;
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.List;
39 import java.util.Optional;
40 import javax.ws.rs.client.Entity;
41 import javax.ws.rs.client.Invocation;
42 import javax.ws.rs.core.GenericType;
43 import javax.ws.rs.core.MediaType;
44 import javax.ws.rs.core.Response;
45 import org.assertj.core.api.AssertionsForClassTypes;
46 import org.glassfish.jersey.client.ClientConfig;
47 import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJaxbJsonProvider;
48 import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJsonProvider;
49 import org.glassfish.jersey.logging.LoggingFeature;
50 import org.glassfish.jersey.server.ResourceConfig;
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.invocation.InvocationOnMock;
57 import org.mockito.stubbing.Answer;
58 import org.openecomp.sdc.be.components.impl.GroupBusinessLogicNew;
59 import org.openecomp.sdc.be.components.validation.AccessValidations;
60 import org.openecomp.sdc.be.components.validation.ComponentValidations;
61 import org.openecomp.sdc.be.config.ConfigurationManager;
62 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
63 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
64 import org.openecomp.sdc.be.datatypes.enums.PromoteVersionEnum;
65 import org.openecomp.sdc.be.impl.ComponentsUtils;
66 import org.openecomp.sdc.be.model.ComponentInstance;
67 import org.openecomp.sdc.be.model.GroupDefinition;
68 import org.openecomp.sdc.be.model.GroupProperty;
69 import org.openecomp.sdc.be.model.Resource;
70 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.GroupsOperation;
71 import org.openecomp.sdc.be.model.operations.StorageException;
72 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
73 import org.openecomp.sdc.be.model.operations.impl.GroupOperation;
74 import org.openecomp.sdc.be.user.UserBusinessLogic;
75 import org.openecomp.sdc.common.api.ConfigurationSource;
76 import org.openecomp.sdc.common.api.Constants;
77 import org.openecomp.sdc.common.impl.ExternalConfiguration;
78 import org.openecomp.sdc.common.impl.FSConfigurationSource;
79 import org.springframework.context.annotation.Bean;
80 import org.springframework.context.annotation.Configuration;
81 import org.springframework.context.annotation.Import;
82 import org.springframework.http.HttpStatus;
84 class GroupEndpointTest extends JerseySpringBaseTest {
86 private static final String VALID_USER = "ab001";
87 private static final String INVALID_USER = "ab002";
88 private static final String VALID_COMPONENT_ID = "12345";
89 private static final String INVALID_COMPONENT_ID = "9999";
90 private static final String VALID_GROUP_ID = "1";
91 private static final String INVALID_GROUP_ID = "2";
92 public static final String A = "a";
93 private static final String VL1 = "VL1";
94 private static final String OLD_VALUE = "old value";
95 private static AccessValidations accessValidations;
96 private static ComponentValidations componentValidations;
97 private static GroupsOperation groupsOperation;
98 private static GroupOperation groupOperation;
100 private GroupDefinition g1;
101 private ComponentInstance ci;
102 private GroupProperty gp1;
105 @Import(BaseTestConfig.class)
106 static class GroupEndpointTestConfig {
109 GroupEndpoint groupEndpoint() {
110 UserBusinessLogic userBusinessLogic = mock(UserBusinessLogic.class);
111 ComponentsUtils componentsUtils = mock(ComponentsUtils.class);
113 return new GroupEndpoint(userBusinessLogic, componentsUtils, groupBusinessLogic());
117 GroupBusinessLogicNew groupBusinessLogic() {
118 return new GroupBusinessLogicNew(accessValidations, componentValidations, groupsOperation, groupOperation);
123 public static void initClass() {
124 ExternalConfiguration.setAppName("catalog-be");
125 String appConfigDir = "src/test/resources/config/catalog-be";
126 ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(),
128 ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
129 //ComponentsUtils needs configuration singleton to be set
130 componentValidations = mock(ComponentValidations.class);
131 accessValidations = mock(AccessValidations.class);
132 groupsOperation = mock(GroupsOperation.class);
133 groupOperation = mock(GroupOperation.class);
138 protected void configureClient(ClientConfig config) {
139 final JacksonJsonProvider jacksonJsonProvider = new JacksonJaxbJsonProvider()
140 .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
141 config.register(jacksonJsonProvider);
145 protected ResourceConfig configure() {
146 forceSet(TestProperties.CONTAINER_PORT, "0");
147 return super.configure(GroupEndpointTestConfig.class)
148 .register(GroupEndpoint.class)
149 .property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, "WARNING");
153 public void before() throws Exception {
156 cr.setSystemName("CR1");
157 g1 = new GroupDefinition();
158 g1.setUniqueId(VALID_GROUP_ID);
159 gp1 = new GroupProperty();
160 gp1.setUniqueId("1");
162 gp1.setValue(OLD_VALUE);
163 g1.setProperties(Arrays.asList(gp1));
164 cr.setGroups(Arrays.asList(g1));
165 ci = new ComponentInstance();
168 happyScenarioSetup();
169 unhappyScenarioSetup();
173 void after() throws Exception {
177 private void unhappyScenarioSetup() {
178 when(accessValidations
179 .validateUserCanWorkOnComponent(eq(INVALID_COMPONENT_ID), eq(ComponentTypeEnum.RESOURCE), eq(VALID_USER),
180 anyString())).thenThrow(new StorageException(NOT_FOUND, INVALID_COMPONENT_ID));
181 when(componentValidations.getComponentInstance(cr, A)).thenReturn(Optional.of(ci));
184 private void happyScenarioSetup() {
185 when(accessValidations
186 .validateUserCanWorkOnComponent(eq(VALID_COMPONENT_ID), any(ComponentTypeEnum.class), eq(VALID_USER),
187 anyString())).thenReturn(cr);
188 when(accessValidations
189 .validateUserCanRetrieveComponentData(eq(VALID_COMPONENT_ID), eq("resources"), eq(VALID_USER), anyString()))
191 when(componentValidations.getComponentInstance(cr, A)).thenReturn(Optional.of(ci));
192 doNothing().when(groupsOperation)
193 .updateGroupOnComponent(eq(VALID_COMPONENT_ID), isA(GroupDefinition.class), any(PromoteVersionEnum.class));
194 when(groupOperation.validateAndUpdatePropertyValue(isA(GroupProperty.class)))
195 .thenReturn(StorageOperationStatus.OK);
197 .updateGroupPropertiesOnComponent(eq(VALID_COMPONENT_ID), isA(GroupDefinition.class), anyList(),
198 any(PromoteVersionEnum.class))).thenAnswer(new Answer<Either>() {
200 public Either answer(InvocationOnMock invocationOnMock) throws Throwable {
201 Object[] args = invocationOnMock.getArguments();
202 return Either.left(Arrays.asList(args[2]));
208 void updateGroupMembers_success() {
209 List<String> ids = Arrays.asList(A);
210 List<String> updatedIds = buildUpdateGroupMembersCall(VALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
211 .post(Entity.entity(ids, MediaType.APPLICATION_JSON), new GenericType<List<String>>() {
213 assertThat(updatedIds.size()).isEqualTo(ids.size());
214 assertThat(updatedIds).containsExactlyInAnyOrder(ids.toArray(new String[ids.size()]));
218 void updateGroupMembersWith2IdenticalMembers_success() {
219 List<String> ids = Arrays.asList(A, A);
220 List<String> updatedIds = buildUpdateGroupMembersCall(VALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
221 .post(Entity.entity(ids, MediaType.APPLICATION_JSON), new GenericType<List<String>>() {
223 assertThat(updatedIds.size()).isEqualTo(1);
224 assertThat(updatedIds).containsExactlyInAnyOrder(String.valueOf(A));
228 void updateGroupMembersWithEmptyList_success() {
229 List<String> ids = new ArrayList<>();
230 List<String> updatedIds = buildUpdateGroupMembersCall(VALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
231 .post(Entity.entity(ids, MediaType.APPLICATION_JSON), new GenericType<List<String>>() {
233 assertThat(updatedIds.size()).isZero();
237 void updateGroupMember_InvalidComponentId_failure() {
238 List<String> ids = new ArrayList<>();
239 Response response = buildUpdateGroupMembersCall(INVALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
240 .post(Entity.entity(ids, MediaType.APPLICATION_JSON), Response.class);
241 AssertionsForClassTypes.assertThat(response.getStatus()).isEqualTo(HttpStatus.NOT_FOUND.value());
245 void updateGroupProperty_success() {
246 GroupProperty property = new GroupProperty();
247 property.setValue("value1");
248 property.setName("prop");
249 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}]";
250 List<GroupProperty> properties = Arrays.asList(property);
251 //TODO define GroupPropertyDTO (after finding other usage in UI code) and improve test coverage
252 // List<GroupProperty> updatedProperties = buildUpdateGroupPropertiesCall(VALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
253 // .put(Entity.entity(propertyStr, MediaType.APPLICATION_JSON), new GenericType<List<GroupProperty>>() {
255 // assertThat(updatedProperties.size()).isEqualTo(1);
256 Response response = buildUpdateGroupPropertiesCall(VALID_COMPONENT_ID, VALID_GROUP_ID, VALID_USER)
257 .put(Entity.entity(propertyStr, MediaType.APPLICATION_JSON));
258 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
262 void getGroupProperties_success() {
263 List<PropertyDataDefinition> properties = buildUpdateGroupPropertiesCall(VALID_COMPONENT_ID, VALID_GROUP_ID,
265 .get(new GenericType<List<PropertyDataDefinition>>() {
267 assertThat(properties.size()).isEqualTo(1);
268 assertThat(properties.get(0).getValue()).isEqualTo(OLD_VALUE);
271 private Invocation.Builder buildUpdateGroupMembersCall(String componentId, String groupId, String userId) {
272 return target("/v1/catalog/resources/" + componentId + "/groups/" + groupId + "/members")
273 .request(MediaType.APPLICATION_JSON)
274 .accept(MediaType.APPLICATION_JSON)
275 .header(Constants.USER_ID_HEADER, userId);
278 private Invocation.Builder buildUpdateGroupPropertiesCall(String componentId, String groupId, String userId) {
279 return target("/v1/catalog/resources/" + componentId + "/groups/" + groupId + "/properties")
280 .request(MediaType.APPLICATION_JSON)
281 .accept(MediaType.APPLICATION_JSON)
282 .header(Constants.USER_ID_HEADER, userId);