Topology tree: test fetchCustomizationIdsFromToscaModelsWhileNeeded
[vid.git] / vid-app-common / src / test / java / org / onap / vid / services / AAITreeNodesEnricherTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 2020 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.onap.vid.services;
22
23 import static java.util.Collections.emptyList;
24 import static java.util.Collections.emptyMap;
25 import static java.util.Collections.singletonMap;
26 import static java.util.stream.Collectors.toList;
27 import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
28 import static org.hamcrest.MatcherAssert.assertThat;
29 import static org.hamcrest.Matchers.allOf;
30 import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
31 import static org.hamcrest.collection.IsMapContaining.hasKey;
32 import static org.hamcrest.core.IsNot.not;
33 import static org.mockito.Matchers.any;
34 import static org.mockito.Mockito.mock;
35 import static org.mockito.Mockito.times;
36 import static org.mockito.Mockito.verify;
37 import static org.mockito.Mockito.when;
38
39 import com.google.common.collect.ImmutableList;
40 import com.google.common.collect.ImmutableMap;
41 import com.google.common.collect.Streams;
42 import java.util.Collection;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.ListIterator;
46 import java.util.Map;
47 import net.javacrumbs.jsonunit.core.Option;
48 import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
49 import org.apache.commons.lang3.builder.ToStringStyle;
50 import org.jetbrains.annotations.NotNull;
51 import org.mockito.InjectMocks;
52 import org.mockito.Mock;
53 import org.onap.vid.aai.AaiClientInterface;
54 import org.onap.vid.aai.model.ModelVer;
55 import org.onap.vid.asdc.parser.ServiceModelInflator;
56 import org.onap.vid.asdc.parser.ServiceModelInflator.Names;
57 import org.onap.vid.exceptions.GenericUncheckedException;
58 import org.onap.vid.model.ServiceModel;
59 import org.onap.vid.model.aaiTree.AAITreeNode;
60 import org.onap.vid.model.aaiTree.NodeType;
61 import org.onap.vid.properties.Features;
62 import org.onap.vid.testUtils.TestUtils;
63 import org.testng.annotations.BeforeMethod;
64 import org.testng.annotations.DataProvider;
65 import org.testng.annotations.Test;
66 import org.togglz.core.manager.FeatureManager;
67
68 public class AAITreeNodesEnricherTest {
69
70     @Mock
71     private AaiClientInterface aaiClient;
72     @Mock
73     private VidService sdcService;
74     @Mock
75     private ServiceModelInflator serviceModelInflator;
76     @Mock
77     private FeatureManager featureManager;
78     @InjectMocks
79     private AAITreeNodesEnricher aaiTreeNodesEnricher;
80
81     @BeforeMethod
82     public void initMocks() {
83         TestUtils.initMockitoMocks(this);
84     }
85
86     private final static String nullString = "null placeholder";
87
88     @Test
89     public void enrichNodesWithModelCustomizationName_simple3NodesCase_nodesEnriched() {
90
91         when(serviceModelInflator.toNamesByVersionId(any())).thenReturn(ImmutableMap.of(
92                 "version id a", new Names("name a", "key a"),
93                 "version id b", new Names("name b", "key b"),
94                 "version id c", new Names("name c", "key c")
95         ));
96
97         final ImmutableList<String> versionIds = ImmutableList.of("version id a", "version id b", "version id c");
98         final ImmutableList<Names> expectedNames = ImmutableList.of(
99                 new Names("name a", "key a"),
100                 new Names("name b", "key b"),
101                 new Names("name c", "key c"));
102
103
104         final List<AAITreeNode> nodesUnderTest = nodesWithVersionIds(versionIds);
105         aaiTreeNodesEnricher.enrichNodesWithModelCustomizationName(nodesUnderTest, null);
106
107         assertThat(toStrings(nodesUnderTest), containsInAnyOrder(toStringsArray(nodesWithVersionIdsAndCustomizationNames(versionIds, expectedNames))));
108     }
109
110     @Test
111     public void enrichNodesWithModelCustomizationName_noNodes_noError() {
112
113         when(serviceModelInflator.toNamesByVersionId(any())).thenReturn(ImmutableMap.of(
114                 "11c6dc3e-cd6a-41b3-a50e-b5a10f7157d0", new Names("my model cust name", "my key")
115         ));
116
117         aaiTreeNodesEnricher.enrichNodesWithModelCustomizationName(emptyList(), null);
118     }
119
120     @Test
121     public void enrichNodesWithModelCustomizationName_nothingInModel_nodesUnchanged() {
122
123         when(serviceModelInflator.toNamesByVersionId(any())).thenReturn(emptyMap());
124
125         final ImmutableList<String> versionIds = ImmutableList.of("version id a", "version id b", "version id c");
126         final Names nullNames = new Names(nullString, nullString);
127         final ImmutableList<Names> expectedNames = ImmutableList.of(nullNames, nullNames, nullNames);
128
129         
130         final List<AAITreeNode> nodesUnderTest = nodesWithVersionIds(versionIds);
131
132         aaiTreeNodesEnricher.enrichNodesWithModelCustomizationName(nodesUnderTest, null);
133
134         assertThat(toStrings(nodesUnderTest), containsInAnyOrder(toStringsArray(nodesWithVersionIdsAndCustomizationNames(versionIds, expectedNames))));
135     }
136
137     @Test
138     public void enrichNodesWithModelCustomizationName_staggered4NodesAndNull_3nodesEnriched2isNull() {
139
140         when(serviceModelInflator.toNamesByVersionId(any())).thenReturn(ImmutableMap.of(
141                 "version id Z", new Names("name Z", "key Z"),
142                 "version id d", new Names(null, "key d"),
143                 "version id c", new Names("name c", null),
144                 "version id a", new Names("name a", "key a")
145         ));
146
147         final ImmutableList<String> versionIds = ImmutableList.of("version id a", "version id b", "version id c", "version id d", nullString);
148         final ImmutableList<Names> expectedNames = ImmutableList.of(
149                 new Names("name a", "key a"),
150                 new Names(nullString, nullString),
151                 new Names("name c", nullString),
152                 new Names(nullString, "key d"),
153                 new Names(nullString, nullString)
154         );
155
156
157         final List<AAITreeNode> nodesUnderTest = nodesWithVersionIds(versionIds);
158
159         aaiTreeNodesEnricher.enrichNodesWithModelCustomizationName(nodesUnderTest, null);
160
161         assertThat(toStrings(nodesUnderTest), containsInAnyOrder(toStringsArray(nodesWithVersionIdsAndCustomizationNames(versionIds, expectedNames))));
162     }
163
164     @DataProvider
165     public static Object[][] enrichVfModulesFilteredOutCases() {
166         AAITreeNode volumeGroup = new AAITreeNode();
167         volumeGroup.setType(NodeType.VOLUME_GROUP);
168
169         AAITreeNode vfModuleWithoutData = new AAITreeNode();
170         vfModuleWithoutData.setType(NodeType.VF_MODULE);
171
172         AAITreeNode vfModuleWithModelCustomizationName = new AAITreeNode();
173         vfModuleWithModelCustomizationName.setType(NodeType.VF_MODULE);
174         vfModuleWithModelCustomizationName.setModelCustomizationName("foo");
175
176         AAITreeNode vfModuleWithKeyInModel = new AAITreeNode();
177         vfModuleWithKeyInModel.setType(NodeType.VF_MODULE);
178         vfModuleWithKeyInModel.setKeyInModel("foo");
179
180         return new Object[][]{
181             {"no nodes", null, true},
182             {"no vfmodules", volumeGroup, true},
183             {"flag is off", vfModuleWithoutData, false},
184             {"all vfmodules with either getKeyInModel or getModelCustomizationId", vfModuleWithModelCustomizationName, true},
185             {"all vfmodules with either getKeyInModel or getModelCustomizationId", vfModuleWithKeyInModel, true},
186         };
187     }
188
189     @Test(dataProvider = "enrichVfModulesFilteredOutCases")
190     public void enrichVfModulesWithModelCustomizationNameFromOtherVersions_givenFilteredOutCases_doNothing(String reasonToSkip, AAITreeNode node, boolean flagState) {
191         when(featureManager.isActive(Features.FLAG_EXP_TOPOLOGY_TREE_VFMODULE_NAMES_FROM_OTHER_TOSCA_VERSIONS))
192             .thenReturn(flagState);
193
194         when(aaiClient.getSortedVersionsByInvariantId(any()))
195             .thenThrow(new AssertionError("did not expect reaching getSortedVersionsByInvariantId"));
196
197         List<AAITreeNode> nodes = (node == null) ? emptyList() : ImmutableList.of(node);
198         aaiTreeNodesEnricher.enrichVfModulesWithModelCustomizationNameFromOtherVersions(nodes, "modelInvariantId");
199     }
200
201     @Test
202     public void enrichVfModulesWithModelCustomizationNameFromOtherVersions_givenMissingKeysFoundInFirstSdcModels_sdcRequestsNotExhausted() {
203         when(featureManager.isActive(Features.FLAG_EXP_TOPOLOGY_TREE_VFMODULE_NAMES_FROM_OTHER_TOSCA_VERSIONS))
204             .thenReturn(true);
205
206         final ListIterator<ModelVer> manyVersionsIterator = manyModelVerIteratorMock();
207
208         String customizationIdToFind = "please-find-me";
209         Names anyNames = mock(Names.class);
210
211         when(serviceModelInflator.toNamesByCustomizationId(any()))
212             .thenReturn(singletonMap("uuidBefore", anyNames))
213             .thenReturn(singletonMap(customizationIdToFind, anyNames))
214             .thenReturn(singletonMap("uuidAfter", anyNames))
215         ;
216
217
218         final Map<String, Names> inOutMutableNamesByCustomizationId = new HashMap<>();
219         aaiTreeNodesEnricher.fetchCustomizationIdsFromToscaModelsWhileNeeded(
220             inOutMutableNamesByCustomizationId, manyVersionsIterator, customizationIdToFind);
221
222         assertThat(inOutMutableNamesByCustomizationId, allOf(
223             hasKey(customizationIdToFind),
224             hasKey("uuidBefore"),
225             not(hasKey("uuidAfter")))
226         );
227
228         verify(manyVersionsIterator, times(2)).next();
229         verify(sdcService, times(2)).getServiceModelOrThrow(any());
230     }
231
232     private ListIterator<ModelVer> manyModelVerIteratorMock() {
233         final ModelVer modelVerMock = mock(ModelVer.class);
234         final ListIterator<ModelVer> result = mock(ListIterator.class);
235
236         when(result.next()).thenReturn(modelVerMock);
237         when(result.hasNext())
238             .thenReturn(true, true, true, true, true, true, false);
239
240         return result;
241     }
242
243     @FunctionalInterface
244     public interface Creator<T, R> {
245         R by(T t);
246     }
247
248     @Test
249     public void enrichVfModulesWithModelCustomizationNameFromOtherVersions() {
250         /*
251         Verifies the following
252
253         [*] aaiClient.getSortedVersionsByInvariantId response is exhausted
254             and all models fetched from sdc
255             -> we can see that model #1 info is populated in nodes
256         [*] relevant nodes enriched
257         [*] where data not found: nodes not enriched
258         [*] where data there already: node left pristine
259         [*] where node is not vfmodule: node left pristine
260
261          */
262
263         String modelInvariantId = "modelInvariantId";
264
265         ///////////// HELPERS
266
267         Creator<Integer, AAITreeNode> nodeMissingData = n -> {
268             AAITreeNode node = new AAITreeNode();
269             node.setType(NodeType.VF_MODULE);
270             node.setModelCustomizationId("model-customization-id-" + n);
271             return node;
272         };
273
274         Creator<Integer, AAITreeNode> nodeWithData = n -> {
275             AAITreeNode node = nodeMissingData.by(n);
276             node.setModelCustomizationName("modelCustomizationName-" + n);
277             node.setKeyInModel("modelKey-" + n);
278             return node;
279         };
280
281         Creator<Integer, ImmutableMap<String, Names>> namesMap = n -> ImmutableMap.of(
282             "model-customization-id-" + n,
283             new Names("modelCustomizationName-" + n, "modelKey-" + n)
284         );
285
286         Creator<Integer, ModelVer> modelVer = n -> {
287             ModelVer m = new ModelVer();
288             m.setModelVersion("model-version-" + n);
289             m.setModelVersionId("model-version-id-" + n);
290             return m;
291         };
292
293         ///////////// SET-UP
294
295         when(featureManager.isActive(Features.FLAG_EXP_TOPOLOGY_TREE_VFMODULE_NAMES_FROM_OTHER_TOSCA_VERSIONS))
296             .thenReturn(true);
297
298         /*
299         +-------------+----------+----------+----------+-----------+-----------+
300         |             | model v1 | model v2 | model v3 | model v77 | model v99 |
301         +-------------+----------+----------+----------+-----------+-----------+
302         | in AAI list |   v      |   v      |   v      |   v       |           |
303         | in SDC      |   v      |   v      |   v      |           |           |
304         | in nodes    |   v      |          |   v      |   v       |   v       |
305         +-------------+----------+----------+----------+-----------+-----------+
306          */
307         when(aaiClient.getSortedVersionsByInvariantId(modelInvariantId))
308             .thenReturn(ImmutableList.of(modelVer.by(3), modelVer.by(77), modelVer.by(2), modelVer.by(1)));
309
310         ServiceModel serviceModel_1 = mock(ServiceModel.class);
311         when(sdcService.getServiceModelOrThrow("model-version-id-1")).thenReturn(serviceModel_1);
312         when(serviceModelInflator.toNamesByCustomizationId(serviceModel_1)).thenReturn(namesMap.by(1));
313
314         ServiceModel serviceModel_2 = mock(ServiceModel.class);
315         when(sdcService.getServiceModelOrThrow("model-version-id-2")).thenReturn(serviceModel_2);
316         when(serviceModelInflator.toNamesByCustomizationId(serviceModel_2)).thenReturn(namesMap.by(2));
317
318         ServiceModel serviceModel_3 = mock(ServiceModel.class);
319         when(sdcService.getServiceModelOrThrow("model-version-id-3")).thenReturn(serviceModel_3);
320         when(serviceModelInflator.toNamesByCustomizationId(serviceModel_3)).thenReturn(namesMap.by(3));
321
322         when(sdcService.getServiceModelOrThrow("model-version-id-77")).thenThrow(GenericUncheckedException.class);
323
324         AAITreeNode nodeWithDataAlready = nodeMissingData.by(1);
325         nodeWithDataAlready.setModelCustomizationName("significant-customization-name");
326         nodeWithDataAlready.setKeyInModel("significant-key-in-model");
327
328         AAITreeNode nodeNotVfModule = nodeMissingData.by(1);
329         nodeNotVfModule.setType(NodeType.GENERIC_VNF);
330
331         Collection<AAITreeNode> nodes = ImmutableList.of(
332             nodeMissingData.by(1), nodeMissingData.by(77),
333             nodeMissingData.by(3), nodeMissingData.by(99),
334             nodeWithDataAlready, nodeNotVfModule
335         );
336
337         ///////////// TEST
338
339         aaiTreeNodesEnricher.enrichVfModulesWithModelCustomizationNameFromOtherVersions(nodes, modelInvariantId);
340
341         assertThat(nodes, jsonEquals(ImmutableList.of(
342             nodeWithData.by(1),
343             nodeWithData.by(3),
344             nodeMissingData.by(77), // not in sdcService
345             nodeMissingData.by(99), // not in aaiClient
346             nodeWithDataAlready, // pristine
347             nodeNotVfModule // pristine
348         )).when(Option.IGNORING_ARRAY_ORDER));
349     }
350
351
352     @NotNull
353     private String[] toStringsArray(List<AAITreeNode> nodes) {
354         return toStrings(nodes).toArray(new String[] {});
355     }
356
357     @NotNull
358     private List<String> toStrings(List<AAITreeNode> nodes) {
359         return nodes.stream().map(n -> {
360             final ReflectionToStringBuilder reflectionToStringBuilder = new ReflectionToStringBuilder(n, ToStringStyle.SHORT_PREFIX_STYLE);
361             reflectionToStringBuilder.setExcludeNullValues(true);
362             return reflectionToStringBuilder.toString();
363         }).collect(toList());
364     }
365
366     @NotNull
367     private List<AAITreeNode> nodesWithVersionIdsAndCustomizationNames(List<String> versionIds, List<Names> customizationNames) {
368         return Streams
369                 .zip(versionIds.stream(), customizationNames.stream(), this::nodeWithVersionIdAndCustomizationName)
370                 .collect(toList());
371     }
372
373     @NotNull
374     private List<AAITreeNode> nodesWithVersionIds(List<String> versionIds) {
375         return versionIds.stream()
376                 .map(versionId -> nodeWithVersionIdAndCustomizationName(versionId, new Names(nullString, nullString)))
377                 .collect(toList());
378     }
379
380     private AAITreeNode nodeWithVersionIdAndCustomizationName(String versionId, Names names) {
381         AAITreeNode newNode = new AAITreeNode();
382         newNode.setModelVersionId(versionId.equals(nullString) ? null : versionId);
383         newNode.setModelCustomizationName(names.getModelCustomizationName().equals(nullString) ? null : names.getModelCustomizationName());
384         newNode.setKeyInModel(names.getModelKey().equals(nullString) ? null : names.getModelKey());
385         return newNode;
386     }
387
388 }