Change to enable SDC list type input
[sdc.git] / catalog-be / src / test / java / org / openecomp / sdc / be / components / property / ComponentInstancePropertyDeclaratorTest.java
1 package org.openecomp.sdc.be.components.property;
2
3 import fj.data.Either;
4 import org.junit.Assert;
5 import org.junit.Test;
6 import org.junit.runner.RunWith;
7 import org.mockito.*;
8 import org.mockito.junit.MockitoJUnitRunner;
9 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
10 import org.openecomp.sdc.be.components.utils.InputsBuilder;
11 import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder;
12 import org.openecomp.sdc.be.components.utils.ResourceBuilder;
13 import org.openecomp.sdc.be.dao.utils.MapUtil;
14 import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
15 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
16 import org.openecomp.sdc.be.model.*;
17 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
18 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
19 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
20 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
21
22 import java.util.*;
23 import java.util.stream.Collectors;
24 import java.util.stream.Stream;
25
26 import static org.assertj.core.api.Assertions.assertThat;
27 import static org.mockito.ArgumentMatchers.eq;
28 import static org.mockito.Mockito.verifyZeroInteractions;
29 import static org.mockito.Mockito.when;
30
31
32 @RunWith(MockitoJUnitRunner.class)
33 public class ComponentInstancePropertyDeclaratorTest extends PropertyDeclaratorTestBase {
34
35     @InjectMocks
36     private ComponentInstancePropertyDeclarator testInstance;
37     @Mock
38     private ToscaOperationFacade toscaOperationFacade;
39     @Mock
40     private ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
41     @Mock
42     private PropertyOperation propertyOperation;
43
44     @Captor
45     private ArgumentCaptor<Map<String, List<ComponentInstanceProperty>>> instancePropertiesCaptor;
46
47     @Test
48     public void declarePropertiesAsInputs_componentInstanceNotExist() {
49         Component cmpt = new Resource();
50         Either<List<InputDefinition>, StorageOperationStatus> createdInputs = testInstance.declarePropertiesAsInputs(cmpt, "someCmptInstId", Collections.emptyList());
51         assertThat(createdInputs.right().value()).isEqualTo(StorageOperationStatus.NOT_FOUND);
52         verifyZeroInteractions(toscaOperationFacade);
53     }
54
55     @Test
56     public void declarePropertiesAsInputs_singleNonComplexProperty() {
57         List<PropertyDataDefinition> properties = Collections.singletonList(prop1);
58         List<ComponentInstancePropInput> propsToDeclare = createInstancePropInputList(properties);
59         when(toscaOperationFacade.addComponentInstancePropertiesToComponent(eq(resource), instancePropertiesCaptor.capture())).thenReturn(Either.left(Collections.emptyMap()));
60         Either<List<InputDefinition>, StorageOperationStatus> createdInputs = testInstance.declarePropertiesAsInputs(resource, "inst1", propsToDeclare);
61         List<InputDefinition> inputs = createdInputs.left().value();
62         List<ComponentInstanceProperty> capturedInstanceProperties = instancePropertiesCaptor.getValue().get(INSTANCE_ID);
63         verifyCreatedInputs(properties, capturedInstanceProperties, inputs);
64         verifyUpdatedProperties(properties, capturedInstanceProperties, inputs);
65     }
66
67     @Test
68     public void declarePropertiesAsInputs_multipleNonComplexProperty() {
69         List<PropertyDataDefinition> properties = Arrays.asList(prop1, prop2);
70         List<ComponentInstancePropInput> propsToDeclare = createInstancePropInputList(properties);
71         when(toscaOperationFacade.addComponentInstancePropertiesToComponent(eq(resource), instancePropertiesCaptor.capture())).thenReturn(Either.left(Collections.emptyMap()));
72         Either<List<InputDefinition>, StorageOperationStatus> createdInputs = testInstance.declarePropertiesAsInputs(resource, "inst1", propsToDeclare);
73
74         List<InputDefinition> inputs = createdInputs.left().value();
75         List<ComponentInstanceProperty> capturedInstanceProperties = instancePropertiesCaptor.getValue().get(INSTANCE_ID);
76         verifyCreatedInputs(properties, capturedInstanceProperties, inputs);
77         verifyUpdatedProperties(properties, capturedInstanceProperties, inputs);
78     }
79
80     @Test
81     public void declarePropertiesAsInputs_singleComplexProperty() {
82         PropertyDefinition innerProp1 = new PropertyDataDefinitionBuilder()
83                 .setName(INNER_PROP1)
84                 .setValue("true")
85                 .setType("boolean")
86                 .setUniqueId(complexProperty.getType() + ".datatype.ecomp_generated_naming")
87                 .build();
88         PropertyDefinition innerProp2 = new PropertyDataDefinitionBuilder()
89                 .setName(INNER_PROP2)
90                 .setValue("abc")
91                 .setType("string")
92                 .setUniqueId(complexProperty.getType() + ".datatype.ecomp_generated_naming")
93                 .build();
94         List<ComponentInstancePropInput> propsToDeclare = createComplexPropInputList(innerProp1, innerProp2);
95         when(toscaOperationFacade.addComponentInstancePropertiesToComponent(eq(resource), instancePropertiesCaptor.capture())).thenReturn(Either.left(Collections.emptyMap()));
96         Either<List<InputDefinition>, StorageOperationStatus> createdInputs = testInstance.declarePropertiesAsInputs(resource, "inst1", propsToDeclare);
97
98         List<InputDefinition> inputs = createdInputs.left().value();
99         List<ComponentInstanceProperty> capturedInstanceProperties = instancePropertiesCaptor.getValue().get(INSTANCE_ID);
100
101         verifyCreatedInputsFromComplexProperty(propsToDeclare, capturedInstanceProperties, inputs);
102         verifyUpdatedComplexProperty(capturedInstanceProperties, inputs);
103     }
104
105     @Test
106     public void declarePropertiesAsListInput() {
107         // construct arguments
108         List<PropertyDataDefinition> properties = Arrays.asList(prop1, prop2);
109         List<ComponentInstancePropInput> propsToDeclare = createInstancePropInputList(properties);
110         InputDefinition input = new InputDefinition(new PropertyDataDefinitionBuilder()
111                 .setName("listinput")
112                 .setType("list")
113                 .setDescription("description")
114                 .setSchemaType("org.onap.datatype.listinput")
115                 .build());
116         // mock returns
117         when(toscaOperationFacade.addComponentInstancePropertiesToComponent(eq(resource), instancePropertiesCaptor.capture())).thenReturn(Either.left(Collections.emptyMap()));
118         Either<InputDefinition, StorageOperationStatus> result = testInstance.declarePropertiesAsListInput(resource, "inst1", propsToDeclare, input);
119         // validate result
120         assertThat(result.isLeft()).isTrue();
121         List<ComponentInstanceProperty> capturedInstanceProperties = instancePropertiesCaptor.getValue().get(INSTANCE_ID);
122         assertThat(capturedInstanceProperties.size()).isEqualTo(2);
123         Map<String, PropertyDataDefinition> propertiesMap =
124                 properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, e->e));
125         for(ComponentInstanceProperty instanceProperty: capturedInstanceProperties) {
126             assertThat(propertiesMap.containsKey(instanceProperty.getName())).isTrue();
127             PropertyDataDefinition property = propertiesMap.get(instanceProperty.getName());
128             assertThat(instanceProperty.getType()).isEqualTo(property.getType());
129             assertThat(instanceProperty.isGetInputProperty()).isTrue();
130         }
131     }
132
133     @Test
134     public void declarePropertiesAsListInput_propertyOwnerNotFound() {
135         // construct arguments
136         List<PropertyDataDefinition> properties = Arrays.asList(prop1, prop2);
137         List<ComponentInstancePropInput> propsToDeclare = createInstancePropInputList(properties);
138         InputDefinition input = new InputDefinition(new PropertyDataDefinitionBuilder()
139                 .setName("listinput")
140                 .setType("list")
141                 .setDescription("description")
142                 .setSchemaType("org.onap.datatype.listinput")
143                 .build());
144         Either<InputDefinition, StorageOperationStatus> result = testInstance.declarePropertiesAsListInput(resource, "inst2", propsToDeclare, input);
145         // validate result
146         assertThat(result.isRight()).isTrue();
147         assertThat(result.right().value()).isEqualTo(StorageOperationStatus.NOT_FOUND);
148     }
149
150     @Test
151     public void unDeclarePropertiesAsListInputsTest() {
152         InputDefinition inputToDelete = new InputDefinition();
153         inputToDelete.setUniqueId(INPUT_ID);
154         inputToDelete.setName(INPUT_ID);
155         inputToDelete.setIsDeclaredListInput(true);
156
157         Component component = createComponentWithListInput(INPUT_ID, "innerPropName");
158         PropertyDefinition prop = new PropertyDataDefinitionBuilder()
159                 .setName("propName")
160                 .setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName"))
161                 .setType("list")
162                 .setUniqueId("propName")
163                 .addGetInputValue(INPUT_ID)
164                 .build();
165         component.setProperties(Collections.singletonList(prop));
166
167         List<ComponentInstanceProperty> ciPropList = new ArrayList<>();
168         ComponentInstanceProperty ciProp = new ComponentInstanceProperty();
169         List<String> pathOfComponentInstances = new ArrayList<>();
170         pathOfComponentInstances.add("pathOfComponentInstances");
171         ciProp.setPath(pathOfComponentInstances);
172         ciProp.setUniqueId("componentInstanceId");
173         ciProp.setDefaultValue("default value");
174         ciProp.setComponentInstanceId("componentInstanceId");
175         ciProp.setComponentInstanceName("componentInstanceName");
176         ciProp.setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName"));
177         ciPropList.add(ciProp);
178
179         when(componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(eq(component), eq(INPUT_ID))).thenReturn(ciPropList);
180         when(propertyOperation.findDefaultValueFromSecondPosition(eq(pathOfComponentInstances), eq(ciProp.getUniqueId()), eq(ciProp.getDefaultValue()))).thenReturn(Either.left(ciProp.getDefaultValue()));
181         when(toscaOperationFacade.updateComponentInstanceProperties(eq(component), eq(ciProp.getComponentInstanceId()), eq(ciPropList))).thenReturn(StorageOperationStatus.OK);
182         StorageOperationStatus storageOperationStatus = testInstance.unDeclarePropertiesAsListInputs(component, inputToDelete);
183
184         assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK);
185     }
186
187     @Test
188     public void unDeclarePropertiesAsListInputsTest_whenNoListInput_returnOk() {
189         InputDefinition input = new InputDefinition();
190         input.setUniqueId(INPUT_ID);
191         input.setName(INPUT_ID);
192         input.setValue("value");
193         List<ComponentInstanceProperty> resList = new ArrayList<>();
194         when(componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(eq(resource), eq(INPUT_ID))).thenReturn(resList);
195         StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input);
196         Assert.assertEquals(status, StorageOperationStatus.OK);
197     }
198     
199     private void verifyUpdatedProperties(List<PropertyDataDefinition> properties, List<ComponentInstanceProperty> capturedInstanceProperties, List<InputDefinition> inputs) {
200         assertThat(capturedInstanceProperties).hasSize(properties.size());
201         Map<String, ComponentInstanceProperty> updatedPropertiesByName = MapUtil.toMap(capturedInstanceProperties, ComponentInstanceProperty::getName);
202         properties.forEach(prop -> verifyUpdatedInstanceProperty(prop, updatedPropertiesByName.get(prop.getName()), inputs));
203     }
204
205     private void verifyUpdatedComplexProperty(List<ComponentInstanceProperty> capturedInstanceProperties, List<InputDefinition> inputs) {
206         assertThat(capturedInstanceProperties).hasSize(1);
207         verifyUpdatedInstanceComplexProperty(capturedInstanceProperties.get(0), inputs);
208     }
209
210     private void verifyCreatedInputs(List<PropertyDataDefinition> originalPropsToDeclare, List<ComponentInstanceProperty> capturedUpdatedProperties, List<InputDefinition> inputs) {
211         assertThat(inputs).hasSize(originalPropsToDeclare.size());
212         Map<String, InputDefinition> propertyIdToCreatedInput = MapUtil.toMap(inputs, InputDefinition::getPropertyId);
213         originalPropsToDeclare.forEach(propToDeclare -> verifyCreatedInput(propToDeclare, propertyIdToCreatedInput.get(propToDeclare.getUniqueId())));
214         capturedUpdatedProperties.forEach(updatedProperty -> verifyInputPropertiesList(updatedProperty, propertyIdToCreatedInput.get(updatedProperty.getUniqueId())));
215     }
216
217     private void verifyCreatedInputsFromComplexProperty(List<ComponentInstancePropInput> propsToDeclare, List<ComponentInstanceProperty> capturedInstanceProperties, List<InputDefinition> inputs) {
218         assertThat(inputs).hasSize(propsToDeclare.size());
219         Map<String, InputDefinition> inputsByName = MapUtil.toMap(inputs, InputDefinition::getName);
220         propsToDeclare.forEach(propToDeclare -> verifyCreatedInputFromComplexProperty(propToDeclare, inputsByName));
221         Map<String, List<InputDefinition>> propertyIdToCreatedInput = MapUtil.groupListBy(inputs, InputDefinition::getPropertyId);
222         capturedInstanceProperties.forEach(updatedProperty -> verifyInputPropertiesListFromComplexProperty(updatedProperty, propertyIdToCreatedInput.get(updatedProperty.getUniqueId())));
223     }
224
225     private void verifyInputPropertiesListFromComplexProperty(ComponentInstanceProperty updatedProperty, List<InputDefinition> inputs) {
226         inputs.forEach(input -> verifyInputPropertiesList(updatedProperty, input));
227     }
228
229     private void verifyCreatedInputFromComplexProperty(ComponentInstancePropInput parentProperty,  Map<String, InputDefinition> inputsByName) {
230         PropertyDefinition innerProperty = parentProperty.getInput();
231         String expectedInputName = generateExpectedInputName(parentProperty, innerProperty);
232         InputDefinition input = inputsByName.get(expectedInputName);
233         assertThat(input.getType()).isEqualTo(innerProperty.getType());
234         assertThat(input.getValue()).isEqualTo(innerProperty.getValue());
235 //        assertThat(input.getDefaultValue()).isEqualTo(innerProperty.getValue());//bug
236         assertThat(input.getUniqueId()).isEqualTo(UniqueIdBuilder.buildPropertyUniqueId(RESOURCE_ID, input.getName()));
237         assertThat(input.getPropertyId()).isEqualTo(parentProperty.getUniqueId());
238         assertThat(input.getInstanceUniqueId()).isEqualTo(INSTANCE_ID);
239
240     }
241
242     private void verifyInputPropertiesList(ComponentInstanceProperty updatedProperty, InputDefinition input) {
243         assertThat(input.getProperties()).hasSize(1);
244         assertThat(updatedProperty).isEqualTo(input.getProperties().get(0));
245     }
246
247
248     private List<ComponentInstancePropInput> createComplexPropInputList(PropertyDefinition ... innerProperties) {
249         return Stream.of(innerProperties).map(this::createComplexPropInput).collect(Collectors.toList());
250     }
251
252     private ComponentInstancePropInput createComplexPropInput(PropertyDefinition innerProp) {
253         ComponentInstancePropInput componentInstancePropInput = new ComponentInstancePropInput(new ComponentInstanceProperty(complexProperty));
254         componentInstancePropInput.setInput(innerProp);
255         componentInstancePropInput.setPropertiesName(complexProperty.getName() + "#" +  innerProp.getName());
256         return componentInstancePropInput;
257     }
258
259     private void verifyUpdatedInstanceProperty(PropertyDataDefinition originalProperty, ComponentInstanceProperty updatedProperty, List<InputDefinition> inputs) {
260         assertThat(updatedProperty.getValue()).isEqualTo(generateGetInputValue(generateExpectedInputName(originalProperty)));
261         assertThat(updatedProperty.isGetInputProperty()).isTrue();
262         assertThat(updatedProperty.getName()).isEqualTo(originalProperty.getName());
263         List<GetInputValueDataDefinition> getInputValues = updatedProperty.getGetInputValues();
264         verifyGetInputValues(getInputValues, inputs);
265     }
266
267     private void verifyUpdatedInstanceComplexProperty(ComponentInstanceProperty updatedComplexProperty, List<InputDefinition> inputs) {
268         assertThat(updatedComplexProperty.getValue()).isEqualTo(generateComplexGetInputValue(inputs));
269         assertThat(updatedComplexProperty.isGetInputProperty()).isTrue();
270         assertThat(updatedComplexProperty.getName()).isEqualTo(complexProperty.getName());
271         List<GetInputValueDataDefinition> getInputValues = updatedComplexProperty.getGetInputValues();
272         verifyGetInputValues(getInputValues, inputs);
273     }
274
275     private void verifyGetInputValues(List<GetInputValueDataDefinition> getInputValues, List<InputDefinition> inputs) {
276         Map<String, InputDefinition> inputsByName = MapUtil.toMap(inputs, InputDefinition::getName);
277         getInputValues.forEach(getInputVal -> {
278             InputDefinition input = inputsByName.get(getInputVal.getInputName());
279             assertThat(input.getUniqueId()).isEqualTo(getInputVal.getInputId());
280         });
281     }
282
283     private String generateComplexGetInputValue(List<InputDefinition> createdInputs) {
284         return String.format("{\"%s\":%s,\"%s\":%s}", INNER_PROP1, generateGetInputValue(createdInputs.get(0).getName()), INNER_PROP2, generateGetInputValue(createdInputs.get(1).getName()));
285     }
286
287     private String generateExpectedInputName(PropertyDataDefinition prop) {
288         return INSTANCE_ID + "_" + prop.getName();
289     }
290
291     private String generateExpectedInputName(PropertyDefinition parentProp, PropertyDefinition innerProperty) {
292         return INSTANCE_ID + "_" + parentProp.getName()+ "_" + innerProperty.getName();
293     }
294
295     private void verifyCreatedInput(PropertyDataDefinition property, InputDefinition input) {
296         assertThat(input.getType()).isEqualTo(property.getType());
297         assertThat(input.getName()).isEqualTo(generateExpectedInputName(property));
298         assertThat(input.getValue()).isEqualTo(property.getValue());
299         assertThat(input.getDefaultValue()).isEqualTo(property.getValue());
300         assertThat(input.getUniqueId()).isEqualTo(UniqueIdBuilder.buildPropertyUniqueId(RESOURCE_ID, input.getName()));
301         assertThat(input.getPropertyId()).isEqualTo(property.getUniqueId());
302         assertThat(input.getInstanceUniqueId()).isEqualTo(INSTANCE_ID);
303     }
304
305     private Component createComponentWithListInput(String inputName, String propName) {
306         InputDefinition input = InputsBuilder.create()
307                 .setName(inputName)
308                 .build();
309
310         input.setUniqueId(INPUT_ID);
311         input.setName(INPUT_ID);
312         input.setDefaultValue("defaultValue");
313         input.setValue(generateGetInputValueAsListInput(inputName, propName));
314
315         return new ResourceBuilder()
316                 .setUniqueId(RESOURCE_ID)
317                 .addInput(input)
318                 .build();
319     }
320 }