2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2021, Nordix Foundation. 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=========================================================
20 package org.openecomp.sdc.be.components.impl;
22 import static org.assertj.core.api.Assertions.assertThat;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.fail;
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.ArgumentMatchers.anyMap;
28 import static org.mockito.ArgumentMatchers.eq;
29 import static org.mockito.Mockito.times;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
33 import fj.data.Either;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.HashMap;
38 import java.util.List;
40 import java.util.Optional;
41 import java.util.stream.Collectors;
42 import org.apache.commons.collections.CollectionUtils;
43 import org.apache.commons.lang3.tuple.ImmutablePair;
44 import org.junit.jupiter.api.BeforeEach;
45 import org.junit.jupiter.api.Test;
46 import org.mockito.ArgumentCaptor;
47 import org.mockito.Captor;
48 import org.mockito.InjectMocks;
49 import org.mockito.Mock;
50 import org.mockito.MockitoAnnotations;
51 import org.openecomp.sdc.be.components.attribute.AttributeDeclarationOrchestrator;
52 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
53 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
54 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
55 import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder;
56 import org.openecomp.sdc.be.components.validation.UserValidations;
57 import org.openecomp.sdc.be.config.ConfigurationManager;
58 import org.openecomp.sdc.be.dao.api.ActionStatus;
59 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
60 import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
61 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
62 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
63 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
64 import org.openecomp.sdc.be.impl.ComponentsUtils;
65 import org.openecomp.sdc.be.model.Component;
66 import org.openecomp.sdc.be.model.ComponentInstOutputsMap;
67 import org.openecomp.sdc.be.model.ComponentInstance;
68 import org.openecomp.sdc.be.model.ComponentInstanceOutput;
69 import org.openecomp.sdc.be.model.ComponentInstanceAttribOutput;
70 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
71 import org.openecomp.sdc.be.model.ComponentParametersView;
72 import org.openecomp.sdc.be.model.DataTypeDefinition;
73 import org.openecomp.sdc.be.model.OutputDefinition;
74 import org.openecomp.sdc.be.model.LifecycleStateEnum;
75 import org.openecomp.sdc.be.model.Resource;
76 import org.openecomp.sdc.be.model.Service;
77 import org.openecomp.sdc.be.model.User;
78 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
79 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
80 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
81 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
82 import org.openecomp.sdc.be.model.operations.impl.AttributeOperation;
83 import org.openecomp.sdc.be.user.UserBusinessLogic;
84 import org.openecomp.sdc.common.api.ConfigurationSource;
85 import org.openecomp.sdc.common.impl.ExternalConfiguration;
86 import org.openecomp.sdc.common.impl.FSConfigurationSource;
87 import org.openecomp.sdc.exception.ResponseFormat;
89 class OutputsBusinessLogicTest {
91 private static final String COMPONENT_INSTANCE_ID = "instanceId";
92 private static final String COMPONENT_ID = "componentId";
93 private static final String USER_ID = "userId";
94 private static final String OUTPUT_ID = "outputId";
95 private static final String OUTPUT_TYPE = "string";
96 private static final String LISTOUTPUT_NAME = "listOutput";
97 private static final String LISTOUTPUT_SCHEMA_TYPE = "org.onap.datatypes.listoutput";
98 private static final String LISTOUTPUT_PROP1_NAME = "prop1";
99 private static final String LISTOUTPUT_PROP1_TYPE = "string";
100 private static final String LISTOUTPUT_PROP2_NAME = "prop2";
101 private static final String LISTOUTPUT_PROP2_TYPE = "integer";
102 private static final String OLD_VALUE = "old value";
103 private static final String NEW_VALUE = "new value";
104 private final ConfigurationManager configurationManager =
105 new ConfigurationManager(new FSConfigurationSource(ExternalConfiguration.getChangeListener(), "src/test/resources/config/catalog-be"));
108 private ComponentsUtils componentsUtilsMock;
111 private UserBusinessLogic userAdminMock;
114 private ToscaOperationFacade toscaOperationFacadeMock;
117 private UserValidations userValidations;
120 private IGraphLockOperation graphLockOperation;
123 private AttributeDeclarationOrchestrator attributeDeclarationOrchestrator;
126 private ApplicationDataTypeCache applicationDataTypeCache;
129 private AttributeOperation attributeOperation;
132 private JanusGraphDao janusGraphDao;
135 private OutputsBusinessLogic testInstance;
137 private Service service;
139 private Map<String, List<ComponentInstanceOutput>> instanceOutputMap;
140 private List<ComponentInstanceOutput> outputsList;
143 public void setUp() {
144 MockitoAnnotations.initMocks(this);
145 service = new Service();
146 service.setUniqueId(COMPONENT_ID);
147 service.setLastUpdaterUserId(USER_ID);
148 service.setIsDeleted(false);
149 service.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
151 testInstance.setUserValidations(userValidations);
152 testInstance.setToscaOperationFacade(toscaOperationFacadeMock);
153 testInstance.setGraphLockOperation(graphLockOperation);
154 testInstance.setComponentsUtils(componentsUtilsMock);
155 testInstance.setJanusGraphDao(janusGraphDao);
156 testInstance.setApplicationDataTypeCache(applicationDataTypeCache);
157 testInstance.setAttributeOperation(attributeOperation);
159 // add a ComponentInstance
160 final ComponentInstance componentInstance = new ComponentInstance();
161 componentInstance.setUniqueId(COMPONENT_INSTANCE_ID);
162 service.setComponentInstances(Collections.singletonList(componentInstance));
164 instanceOutputMap = new HashMap<>();
165 final ComponentInstanceOutput componentInstanceOutput = new ComponentInstanceOutput();
166 componentInstanceOutput.setOutputId(OUTPUT_ID);
167 componentInstanceOutput.setName(OUTPUT_ID);
168 outputsList = Collections.singletonList(componentInstanceOutput);
169 instanceOutputMap.put(COMPONENT_INSTANCE_ID, outputsList);
170 instanceOutputMap.put("someOutputId", Collections.singletonList(new ComponentInstanceOutput()));
171 service.setComponentInstancesOutputs(instanceOutputMap);
172 when(userValidations.validateUserExists(USER_ID)).thenReturn(new User());
173 when(userAdminMock.getUser(USER_ID, false)).thenReturn(new User());
177 void getComponentInstanceOutputs_ComponentInstanceNotExist() {
178 when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))).thenReturn(Either.left(service));
179 final Either<List<ComponentInstanceOutput>, ResponseFormat> componentInstanceOutputs = testInstance
180 .getComponentInstanceOutputs(USER_ID, COMPONENT_ID, "nonExisting");
181 assertThat(componentInstanceOutputs.isRight()).isTrue();
182 verify(componentsUtilsMock).getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND);
186 void getComponentInstanceOutputs_emptyOutputsMap() {
187 service.setComponentInstancesOutputs(Collections.emptyMap());
188 getComponents_emptyOutputs(service);
192 void getComponentInstanceOutputs_nullOutputsMap() {
193 service.setComponentInstancesOutputs(null);
194 getComponents_emptyOutputs(service);
198 void getComponentInstanceOutputs_instanceHasNoOutputs() {
199 service.setComponentInstancesOutputs(Collections.singletonMap("someOutputId", new ArrayList<>()));
200 getComponents_emptyOutputs(service);
204 void getComponentInstanceOutputs() {
205 when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))).thenReturn(Either.left(service));
206 final Either<List<ComponentInstanceOutput>, ResponseFormat> componentInstanceOutputs = testInstance
207 .getComponentInstanceOutputs(USER_ID, COMPONENT_ID, COMPONENT_INSTANCE_ID);
208 assertEquals("outputId", componentInstanceOutputs.left().value().get(0).getOutputId());
212 void testDeclareAttributes() {
213 service.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
214 service.setLastUpdaterUserId(USER_ID);
215 final ComponentInstOutputsMap componentInstOutputsMap = new ComponentInstOutputsMap();
216 final Map<String, List<ComponentInstanceAttribOutput>> propertiesForDeclaration = new HashMap<>();
217 propertiesForDeclaration.put(COMPONENT_ID, getPropertiesListForDeclaration());
219 final List<OutputDefinition> declaredPropertiesToOutputs = getDeclaredProperties();
220 initMockitoStubbings(declaredPropertiesToOutputs);
222 final Either<List<OutputDefinition>, ResponseFormat> declaredPropertiesEither =
223 testInstance.declareAttributes(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, componentInstOutputsMap);
225 assertThat(declaredPropertiesEither.isLeft()).isTrue();
227 final List<OutputDefinition> declaredProperties = declaredPropertiesEither.left().value();
228 assertThat(CollectionUtils.isNotEmpty(declaredProperties)).isTrue();
229 assertEquals(1, declaredProperties.size());
230 assertEquals(declaredProperties, declaredPropertiesToOutputs);
234 void testDeclareAttributes_fail() {
235 service.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
236 service.setLastUpdaterUserId(USER_ID);
237 final ComponentInstOutputsMap componentInstOutputsMap = new ComponentInstOutputsMap();
238 final Map<String, List<ComponentInstanceAttribOutput>> propertiesForDeclaration = new HashMap<>();
239 propertiesForDeclaration.put(COMPONENT_ID, getPropertiesListForDeclaration());
241 final List<OutputDefinition> declaredPropertiesToOutputs = getDeclaredProperties();
242 initMockitoStubbings(declaredPropertiesToOutputs);
243 when(attributeDeclarationOrchestrator.declareAttributesToOutputs(any(), any())).thenThrow(ByResponseFormatComponentException.class);
244 final Either<List<OutputDefinition>, ResponseFormat> declaredPropertiesEither =
245 testInstance.declareAttributes(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, componentInstOutputsMap);
247 assertThat(declaredPropertiesEither.isRight()).isTrue();
251 private void initMockitoStubbings(List<OutputDefinition> declaredPropertiesToOutputs) {
252 when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))).thenReturn(
253 Either.left(service));
254 when(attributeDeclarationOrchestrator.declareAttributesToOutputs(any(), any())).thenReturn(Either.left(
255 declaredPropertiesToOutputs));
256 when(toscaOperationFacadeMock.addOutputsToComponent(any(), any())).thenReturn(Either.left(declaredPropertiesToOutputs));
257 when(janusGraphDao.commit()).thenReturn(JanusGraphOperationStatus.OK);
258 when(graphLockOperation.lockComponent(any(), any())).thenReturn(StorageOperationStatus.OK);
259 when(graphLockOperation.unlockComponent(any(), any())).thenReturn(StorageOperationStatus.OK);
262 private void getComponents_emptyOutputs(Service service) {
263 when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))).thenReturn(Either.left(service));
264 final Either<List<ComponentInstanceOutput>, ResponseFormat> componentInstanceOutputs = testInstance
265 .getComponentInstanceOutputs(USER_ID, COMPONENT_ID, COMPONENT_INSTANCE_ID);
266 assertEquals(Collections.emptyList(), componentInstanceOutputs.left().value());
269 private List<ComponentInstanceAttribOutput> getPropertiesListForDeclaration() {
270 return outputsList.stream().map(this::getPropertyForDeclaration).collect(Collectors.toList());
273 private ComponentInstanceAttribOutput getPropertyForDeclaration(ComponentInstanceOutput componentInstanceOutput) {
274 final ComponentInstanceAttribOutput propOutput = new ComponentInstanceAttribOutput();
275 propOutput.setOutput(componentInstanceOutput);
276 propOutput.setAttributesName(componentInstanceOutput.getName());
281 private List<OutputDefinition> getDeclaredProperties() {
282 return outputsList.stream().map(OutputDefinition::new).collect(Collectors.toList());
285 private OutputDefinition setUpListOutput() {
286 final OutputDefinition listOutput = new OutputDefinition();
287 listOutput.setName(LISTOUTPUT_NAME);
288 listOutput.setType("list");
293 void test_deleteOutput_listOutput_fail_getComponent() throws Exception {
294 when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
295 .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
296 when(componentsUtilsMock.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND)).thenReturn(ActionStatus.RESOURCE_NOT_FOUND);
299 testInstance.deleteOutput(COMPONENT_ID, USER_ID, LISTOUTPUT_NAME);
300 } catch (ComponentException e) {
301 assertEquals(ActionStatus.RESOURCE_NOT_FOUND, e.getActionStatus());
302 verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class));
309 void test_deleteOutput_listOutput_fail_validateOutput() throws Exception {
310 final OutputDefinition listOutput = setUpListOutput();
311 final String outputId = COMPONENT_ID + "." + listOutput.getName();
312 listOutput.setUniqueId(outputId);
313 service.setOutputs(Collections.singletonList(listOutput));
314 final String NONEXIST_OUTPUT_NAME = "myOutput";
316 when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
317 .thenReturn(Either.left(service));
320 testInstance.deleteOutput(COMPONENT_ID, USER_ID, NONEXIST_OUTPUT_NAME);
321 } catch (ComponentException e) {
322 assertEquals(ActionStatus.OUTPUT_IS_NOT_CHILD_OF_COMPONENT, e.getActionStatus());
323 verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class));
330 void test_deleteOutput_listOutput_fail_lockComponent() throws Exception {
331 final OutputDefinition listOutput = setUpListOutput();
332 final String outputId = COMPONENT_ID + "." + listOutput.getName();
333 listOutput.setUniqueId(outputId);
334 service.setOutputs(Collections.singletonList(listOutput));
336 when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
337 .thenReturn(Either.left(service));
338 when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.NOT_FOUND);
339 when(componentsUtilsMock.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND, ComponentTypeEnum.SERVICE))
340 .thenReturn(ActionStatus.SERVICE_NOT_FOUND);
343 testInstance.deleteOutput(COMPONENT_ID, USER_ID, outputId);
344 } catch (ComponentException e) {
345 assertEquals(ActionStatus.SERVICE_NOT_FOUND, e.getActionStatus());
346 verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class));
347 verify(graphLockOperation, times(1)).lockComponent(COMPONENT_ID, NodeTypeEnum.Service);
354 void test_deleteOutput_listOutput_fail_deleteOutput() throws Exception {
355 final OutputDefinition listOutput = setUpListOutput();
356 final String outputId = COMPONENT_ID + "." + listOutput.getName();
357 listOutput.setUniqueId(outputId);
358 service.setOutputs(Collections.singletonList(listOutput));
360 when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
361 .thenReturn(Either.left(service));
362 when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
363 when(toscaOperationFacadeMock.deleteOutputOfResource(service, listOutput.getName())).thenReturn(StorageOperationStatus.BAD_REQUEST);
364 when(componentsUtilsMock.convertFromStorageResponse(StorageOperationStatus.BAD_REQUEST)).thenReturn(ActionStatus.INVALID_CONTENT);
367 testInstance.deleteOutput(COMPONENT_ID, USER_ID, outputId);
368 } catch (ComponentException e) {
369 assertEquals(ActionStatus.INVALID_CONTENT, e.getActionStatus());
370 verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class));
371 verify(graphLockOperation, times(1)).lockComponent(COMPONENT_ID, NodeTypeEnum.Service);
372 verify(toscaOperationFacadeMock, times(1)).deleteOutputOfResource(service, listOutput.getName());
379 void test_deleteOutput_output_fail_unDeclare() throws Exception {
380 final OutputDefinition listOutput = setUpListOutput();
381 final String outputId = COMPONENT_ID + "." + listOutput.getName();
382 listOutput.setUniqueId(outputId);
383 service.setOutputs(Collections.singletonList(listOutput));
385 when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
386 .thenReturn(Either.left(service));
387 when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
388 when(toscaOperationFacadeMock.deleteOutputOfResource(service, listOutput.getName())).thenReturn(StorageOperationStatus.OK);
389 when(attributeDeclarationOrchestrator.unDeclareAttributesAsOutputs(service, listOutput)).thenReturn(StorageOperationStatus.BAD_REQUEST);
390 when(componentsUtilsMock.convertFromStorageResponse(StorageOperationStatus.BAD_REQUEST)).thenReturn(ActionStatus.INVALID_CONTENT);
393 testInstance.deleteOutput(COMPONENT_ID, USER_ID, outputId);
394 } catch (ComponentException e) {
395 assertEquals(ActionStatus.INVALID_CONTENT, e.getActionStatus());
396 verify(attributeDeclarationOrchestrator, times(1)).unDeclareAttributesAsOutputs(service, listOutput);
403 void test_deleteOutput_output_success() throws Exception {
404 final OutputDefinition listOutput = setUpListOutput();
405 final String outputId = COMPONENT_ID + "." + listOutput.getName();
406 listOutput.setUniqueId(outputId);
407 service.setOutputs(Collections.singletonList(listOutput));
409 when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
410 .thenReturn(Either.left(service));
411 when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
412 when(toscaOperationFacadeMock.deleteOutputOfResource(service, listOutput.getName())).thenReturn(StorageOperationStatus.OK);
413 when(attributeDeclarationOrchestrator.unDeclareAttributesAsOutputs(service, listOutput)).thenReturn(StorageOperationStatus.OK);
415 testInstance.deleteOutput(COMPONENT_ID, USER_ID, outputId);
416 verify(attributeDeclarationOrchestrator, times(1)).unDeclareAttributesAsOutputs(service, listOutput);