Implement Attributes/Outputs BE (part 3)
[sdc.git] / catalog-be / src / test / java / org / openecomp / sdc / be / components / impl / OutputsBusinessLogicTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
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 package org.openecomp.sdc.be.components.impl;
21
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;
32
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;
39 import java.util.Map;
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;
88
89 class OutputsBusinessLogicTest {
90
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"));
106
107     @Mock
108     private ComponentsUtils componentsUtilsMock;
109
110     @Mock
111     private UserBusinessLogic userAdminMock;
112
113     @Mock
114     private ToscaOperationFacade toscaOperationFacadeMock;
115
116     @Mock
117     private UserValidations userValidations;
118
119     @Mock
120     private IGraphLockOperation graphLockOperation;
121
122     @Mock
123     private AttributeDeclarationOrchestrator attributeDeclarationOrchestrator;
124
125     @Mock
126     private ApplicationDataTypeCache applicationDataTypeCache;
127
128     @Mock
129     private AttributeOperation attributeOperation;
130
131     @Mock
132     private JanusGraphDao janusGraphDao;
133
134     @InjectMocks
135     private OutputsBusinessLogic testInstance;
136
137     private Service service;
138
139     private Map<String, List<ComponentInstanceOutput>> instanceOutputMap;
140     private List<ComponentInstanceOutput> outputsList;
141
142     @BeforeEach
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);
150
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);
158
159         // add a ComponentInstance
160         final ComponentInstance componentInstance = new ComponentInstance();
161         componentInstance.setUniqueId(COMPONENT_INSTANCE_ID);
162         service.setComponentInstances(Collections.singletonList(componentInstance));
163
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());
174     }
175
176     @Test
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);
183     }
184
185     @Test
186     void getComponentInstanceOutputs_emptyOutputsMap() {
187         service.setComponentInstancesOutputs(Collections.emptyMap());
188         getComponents_emptyOutputs(service);
189     }
190
191     @Test
192     void getComponentInstanceOutputs_nullOutputsMap() {
193         service.setComponentInstancesOutputs(null);
194         getComponents_emptyOutputs(service);
195     }
196
197     @Test
198     void getComponentInstanceOutputs_instanceHasNoOutputs() {
199         service.setComponentInstancesOutputs(Collections.singletonMap("someOutputId", new ArrayList<>()));
200         getComponents_emptyOutputs(service);
201     }
202
203     @Test
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());
209     }
210
211     @Test
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());
218
219         final List<OutputDefinition> declaredPropertiesToOutputs = getDeclaredProperties();
220         initMockitoStubbings(declaredPropertiesToOutputs);
221
222         final Either<List<OutputDefinition>, ResponseFormat> declaredPropertiesEither =
223             testInstance.declareAttributes(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, componentInstOutputsMap);
224
225         assertThat(declaredPropertiesEither.isLeft()).isTrue();
226
227         final List<OutputDefinition> declaredProperties = declaredPropertiesEither.left().value();
228         assertThat(CollectionUtils.isNotEmpty(declaredProperties)).isTrue();
229         assertEquals(1, declaredProperties.size());
230         assertEquals(declaredProperties, declaredPropertiesToOutputs);
231     }
232
233     @Test
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());
240
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);
246
247         assertThat(declaredPropertiesEither.isRight()).isTrue();
248
249     }
250
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);
260     }
261
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());
267     }
268
269     private List<ComponentInstanceAttribOutput> getPropertiesListForDeclaration() {
270         return outputsList.stream().map(this::getPropertyForDeclaration).collect(Collectors.toList());
271     }
272
273     private ComponentInstanceAttribOutput getPropertyForDeclaration(ComponentInstanceOutput componentInstanceOutput) {
274         final ComponentInstanceAttribOutput propOutput = new ComponentInstanceAttribOutput();
275         propOutput.setOutput(componentInstanceOutput);
276         propOutput.setAttributesName(componentInstanceOutput.getName());
277
278         return propOutput;
279     }
280
281     private List<OutputDefinition> getDeclaredProperties() {
282         return outputsList.stream().map(OutputDefinition::new).collect(Collectors.toList());
283     }
284
285     private OutputDefinition setUpListOutput() {
286         final OutputDefinition listOutput = new OutputDefinition();
287         listOutput.setName(LISTOUTPUT_NAME);
288         listOutput.setType("list");
289         return listOutput;
290     }
291
292     @Test
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);
297
298         try {
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));
303             return;
304         }
305         fail();
306     }
307
308     @Test
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";
315
316         when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
317             .thenReturn(Either.left(service));
318
319         try {
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));
324             return;
325         }
326         fail();
327     }
328
329     @Test
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));
335
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);
341
342         try {
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);
348             return;
349         }
350         fail();
351     }
352
353     @Test
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));
359
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);
365
366         try {
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());
373             return;
374         }
375         fail();
376     }
377
378     @Test
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));
384
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);
391
392         try {
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);
397             return;
398         }
399         fail();
400     }
401
402     @Test
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));
408
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);
414
415         testInstance.deleteOutput(COMPONENT_ID, USER_ID, outputId);
416         verify(attributeDeclarationOrchestrator, times(1)).unDeclareAttributesAsOutputs(service, listOutput);
417     }
418
419 }