Fix for Penetration test _ Session and cookie management
[vid.git] / vid-app-common / src / test / java / org / onap / vid / services / AAITreeNodeBuilderTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 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
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.Comparator.comparing;
24 import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
25 import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER;
26 import static net.javacrumbs.jsonunit.core.Option.IGNORING_EXTRA_FIELDS;
27 import static org.hamcrest.MatcherAssert.assertThat;
28 import static org.hamcrest.Matchers.empty;
29 import static org.hamcrest.core.Is.is;
30 import static org.junit.Assert.assertEquals;
31 import static org.mockito.Mockito.when;
32 import static org.onap.vid.services.AAIServiceTree.AAI_TREE_PATHS;
33 import static org.onap.vid.testUtils.TestUtils.initMockitoMocks;
34 import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
35 import static org.testng.Assert.assertNull;
36 import static org.testng.Assert.assertTrue;
37
38 import com.fasterxml.jackson.databind.JsonNode;
39 import com.fasterxml.jackson.databind.ObjectMapper;
40 import com.fasterxml.jackson.databind.node.ArrayNode;
41 import com.fasterxml.jackson.databind.node.ObjectNode;
42 import com.google.common.collect.ImmutableList;
43 import com.google.common.collect.ImmutableMap;
44 import com.google.common.util.concurrent.MoreExecutors;
45 import java.io.IOException;
46 import java.util.HashMap;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.Optional;
50 import java.util.concurrent.ConcurrentSkipListSet;
51 import java.util.concurrent.ExecutorService;
52 import java.util.concurrent.Executors;
53 import org.apache.commons.lang3.exception.ExceptionUtils;
54 import org.apache.commons.lang3.tuple.Pair;
55 import org.apache.log4j.LogManager;
56 import org.apache.log4j.Logger;
57 import org.jetbrains.annotations.NotNull;
58 import org.mockito.Mock;
59 import org.mockito.stubbing.Answer;
60 import org.onap.vid.aai.AaiClientInterface;
61 import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship;
62 import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList;
63 import org.onap.vid.exceptions.GenericUncheckedException;
64 import org.onap.vid.model.aaiTree.AAITreeNode;
65 import org.onap.vid.model.aaiTree.NodeType;
66 import org.onap.vid.mso.model.CloudConfiguration;
67 import org.onap.vid.testUtils.TestUtils;
68 import org.onap.vid.utils.Logging;
69 import org.onap.vid.utils.Tree;
70 import org.onap.vid.utils.Unchecked;
71 import org.springframework.http.HttpMethod;
72 import org.testng.annotations.BeforeMethod;
73 import org.testng.annotations.DataProvider;
74 import org.testng.annotations.Test;
75
76 public class AAITreeNodeBuilderTest {
77
78     private AAITreeNodeBuilder aaiTreeNodeBuilder;
79
80     @Mock
81     private AaiClientInterface aaiClientMock;
82
83     private ExecutorService executorService;
84     private Logging logging = new Logging();
85     private static final Logger logger = LogManager.getLogger(AAITreeNodeBuilderTest.class);
86
87     private static final ObjectMapper mapper = new ObjectMapper();
88
89     @BeforeMethod
90     public void initMocks() {
91         initMockitoMocks(this);
92         aaiTreeNodeBuilder = new AAITreeNodeBuilder(aaiClientMock, logging);
93         executorService = MoreExecutors.newDirectExecutorService();
94     }
95
96     private void buildNodeAndAssert(JsonNode inputNode, AAITreeNode expectedNode, NodeType nodeType){
97         ConcurrentSkipListSet<AAITreeNode> nodesAccumulator = new ConcurrentSkipListSet<>(comparing(AAITreeNode::getUniqueNodeKey));
98         when(aaiClientMock.typedAaiRest(Unchecked.toURI("anyUrl"), JsonNode.class, null, HttpMethod.GET, false)).thenReturn(inputNode);
99         AAITreeNode actualNode;
100         try {
101             actualNode = aaiTreeNodeBuilder.buildNode(
102                 nodeType,
103                 "anyUrl",
104                 null,
105                 HttpMethod.GET,
106                 nodesAccumulator,
107                 executorService,
108                 AAI_TREE_PATHS.getSubTree(new AAIServiceTree.AaiRelationship(nodeType))
109             ).get(0);
110         } catch (Throwable e) {
111             //print stack traces for more information in case of failure
112             System.out.println("Failed to build node by aaiTreeNodeBuilder");
113             ExceptionUtils.getThrowableList(e)
114                 .stream()
115                 .peek(it ->System.err.println(it.getLocalizedMessage()))
116                 .forEach(Throwable::printStackTrace);
117             throw e;
118         }
119         assertThat(actualNode, jsonEquals(expectedNode).when(IGNORING_ARRAY_ORDER, IGNORING_EXTRA_FIELDS).whenIgnoringPaths("relationshipList","children[0].relationshipList"));
120     }
121
122     @Test
123     public void buildNode_buildGroupNode_NodeIsAsExpected() {
124         buildNodeAndAssert(createGroupJson(), createExpectedGroupNode(), NodeType.INSTANCE_GROUP);
125     }
126
127     private AAITreeNode createExpectedGroupNode() {
128         AAITreeNode expectedNode = new AAITreeNode();
129         expectedNode.setId("c4fcf022-31a0-470a-b5b8-c18335b7af32");
130         expectedNode.setType(NodeType.INSTANCE_GROUP);
131         expectedNode.setName("Test vE-Flex");
132         expectedNode.setModelVersionId("Test vE-Flex");
133         expectedNode.setModelInvariantId("dd182d7d-6949-4b90-b3cc-5befe400742e");
134         expectedNode.setInMaint(false);
135         HashMap<String,Object> additionalProperties = new HashMap<>();
136         additionalProperties.put("inMaint","false");
137         additionalProperties.put("description","Test vE-Flex instance-group");
138         additionalProperties.put("instance-group-type","ha");
139         additionalProperties.put("instance-group-role","test-IG-role");
140         additionalProperties.put("resource-version","1533315433086");
141         additionalProperties.put("instance-group-function","vTSBC Customer Landing Network Collection");
142         expectedNode.setAdditionalProperties(additionalProperties);
143         return expectedNode;
144     }
145
146     private JsonNode createGroupJson() {
147         ObjectMapper objectMapper = new ObjectMapper();
148         JsonNode groupNode = null;
149         try {
150             groupNode = objectMapper.readTree("" +
151                     "{" +
152                     "      \"id\": \"c4fcf022-31a0-470a-b5b8-c18335b7af32\"," +
153                     "      \"instance-group-role\": \"test-IG-role\"," +
154                     "      \"description\": \"Test vE-Flex instance-group\"," +
155                     "      \"instance-group-type\": \"ha\"," +
156                     "      \"resource-version\": \"1533315433086\"," +
157                     "      \"instance-group-name\": \"Test vE-Flex\"," +
158                     "      \"model-invariant-id\": \"dd182d7d-6949-4b90-b3cc-5befe400742e\"," +
159                     "      \"model-version-id\": \"Test vE-Flex\"," +
160                     "      \"inMaint\": \"false\"," +
161                     "      \"instance-group-function\": \"vTSBC Customer Landing Network Collection\"," +
162                     "      \"relationship-list\": {" +
163                     "      \"relationship\": []" +
164                     "    }" +
165                     "    }");
166         } catch (IOException e) {
167             e.printStackTrace();
168         }
169         return groupNode;
170     }
171
172     @Test
173     public void whenReadNetworkNode_thenNodeIsAsExpected() throws IOException {
174         JsonNode mockedAaiResponse = TestUtils.readJsonResourceFileAsObject("/getTopology/network.json", JsonNode.class);
175
176         AAITreeNode expectedNetworkNode = new AAITreeNode();
177         expectedNetworkNode.setId("94c86b39-bbbf-4027-8120-ff37c6d2493a");
178         expectedNetworkNode.setName("AUK51a_oam_calea_net_1");
179         expectedNetworkNode.setOrchestrationStatus("Assigned");
180         expectedNetworkNode.setModelInvariantId("b9a9b549-0ee4-49fc-b4f2-5edc6701da68");
181         expectedNetworkNode.setModelVersionId("77010093-df36-4dcb-8428-c3d02bf3f88d");
182         expectedNetworkNode.setModelCustomizationId("e5f33853-f84c-4cdd-99f2-93846957aa18");
183         expectedNetworkNode.setType(NodeType.NETWORK);
184         expectedNetworkNode.setCloudConfiguration(new CloudConfiguration("auk51a", "b530fc990b6d4334bd45518bebca6a51", "att-nc"));
185
186         buildNodeAndAssert(mockedAaiResponse, expectedNetworkNode, NodeType.NETWORK);
187     }
188
189     @Test
190     public void whenCloudRegionMissing_otherPlacementFieldsReadAsExpected() throws IOException {
191
192         AAITreeNode node = new AAITreeNode();
193         Optional<Relationship> tenantRelationShip = Optional.of(
194                 JACKSON_OBJECT_MAPPER.readValue("{" +
195                         "      \"related-to\": \"tenant\"," +
196                         "      \"relationship-label\": \"org.onap.relationships.inventory.Uses\"," +
197                         "      \"related-link\": \"/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-nc/auk51a/tenants/tenant/b530fc990b6d4334bd45518bebca6a51\"," +
198                         "      \"relationship-data\": [{" +
199                         "        \"relationship-key\": \"cloud-region.cloud-owner\"," +
200                         "        \"relationship-value\": \"att-nc\"" +
201                         "      }, {" +
202                         "        \"relationship-key\": \"tenant.tenant-id\"," +
203                         "        \"relationship-value\": \"b530fc990b6d4334bd45518bebca6a51\"" +
204                         "      }" +
205                         "      ]," +
206                         "      \"related-to-property\": [{" +
207                         "        \"property-key\": \"tenant.tenant-name\"," +
208                         "        \"property-value\": \"ecomp_ispt\"" +
209                         "      }" +
210                         "      ]" +
211                         "    }", Relationship.class)
212         );
213         aaiTreeNodeBuilder.enrichPlacementDataUsingTenantInfo(node, tenantRelationShip);
214         assertEquals(new CloudConfiguration(null, "b530fc990b6d4334bd45518bebca6a51", "att-nc"), node.getCloudConfiguration());
215     }
216
217     @Test
218     public void whenTenantMissing_otherPlacementFieldsReadAsExpected() throws IOException {
219
220         AAITreeNode node = new AAITreeNode();
221         Optional<Relationship> tenantRelationShip = Optional.of(
222                 JACKSON_OBJECT_MAPPER.readValue("{" +
223                         "      \"related-to\": \"tenant\"," +
224                         "      \"relationship-label\": \"org.onap.relationships.inventory.Uses\"," +
225                         "      \"related-link\": \"/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-nc/auk51a/tenants/tenant/b530fc990b6d4334bd45518bebca6a51\"," +
226                         "      \"relationship-data\": [{" +
227                         "        \"relationship-key\": \"cloud-region.cloud-owner\"," +
228                         "        \"relationship-value\": \"att-nc\"" +
229                         "      }, {" +
230                         "        \"relationship-key\": \"cloud-region.cloud-region-id\"," +
231                         "        \"relationship-value\": \"auk51a\"" +
232                         "      }" +
233                         "      ]," +
234                         "      \"related-to-property\": [{" +
235                         "        \"property-key\": \"tenant.tenant-name\"," +
236                         "        \"property-value\": \"ecomp_ispt\"" +
237                         "      }" +
238                         "      ]" +
239                         "    }", Relationship.class)
240         );
241         aaiTreeNodeBuilder.enrichPlacementDataUsingTenantInfo(node, tenantRelationShip);
242         assertEquals(new CloudConfiguration("auk51a", null, "att-nc"), node.getCloudConfiguration());
243     }
244
245     @Test
246     public void whenCloudOwnerMissing_otherPlacementFieldsReadAsExpected() throws IOException {
247
248         AAITreeNode node = new AAITreeNode();
249         Optional<Relationship> tenantRelationShip = Optional.of(
250                 JACKSON_OBJECT_MAPPER.readValue("{" +
251                         "      \"related-to\": \"tenant\"," +
252                         "      \"relationship-label\": \"org.onap.relationships.inventory.Uses\"," +
253                         "      \"related-link\": \"/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-nc/auk51a/tenants/tenant/b530fc990b6d4334bd45518bebca6a51\"," +
254                         "      \"relationship-data\": [{" +
255                         "        \"relationship-key\": \"tenant.tenant-id\"," +
256                         "        \"relationship-value\": \"b530fc990b6d4334bd45518bebca6a51\"" +
257                         "      }, {" +
258                         "        \"relationship-key\": \"cloud-region.cloud-region-id\"," +
259                         "        \"relationship-value\": \"auk51a\"" +
260                         "      }" +
261                         "      ]," +
262                         "      \"related-to-property\": [{" +
263                         "        \"property-key\": \"tenant.tenant-name\"," +
264                         "        \"property-value\": \"ecomp_ispt\"" +
265                         "      }" +
266                         "      ]" +
267                         "    }", Relationship.class)
268         );
269         aaiTreeNodeBuilder.enrichPlacementDataUsingTenantInfo(node, tenantRelationShip);
270         assertEquals(new CloudConfiguration("auk51a", "b530fc990b6d4334bd45518bebca6a51",  null), node.getCloudConfiguration());
271     }
272
273     @Test
274     public void whenThereIsNoTenantRelationship_thenPlacementIsNull() throws IOException {
275         AAITreeNode node = new AAITreeNode();
276         aaiTreeNodeBuilder.enrichPlacementData(node);
277         assertNull(node.getCloudConfiguration());
278     }
279
280
281     @Test
282     public void whenReadVnfNodeWithVfModule_thenNodeIsAsExpected() throws IOException {
283         JsonNode mockedAaiGetVnfResponse = TestUtils.readJsonResourceFileAsObject("/getTopology/vnf.json", JsonNode.class);
284
285         //add mock for vfModule of the VNF
286         JsonNode mockedAaiGetVfModuleResponse = TestUtils.readJsonResourceFileAsObject("/getTopology/vfModule.json", JsonNode.class);
287         when(aaiClientMock.typedAaiGet(Unchecked.toURI("anyUrl/vf-modules"), JsonNode.class)).thenReturn(mockedAaiGetVfModuleResponse);
288
289         CloudConfiguration expectedCloudConfiguration = new CloudConfiguration("dyh3b", "c8035f5ee95d4c62bbc8074c044122b9", "irma-aic");
290
291         AAITreeNode expectedVnfNode = createExpectedVnfTreeNode(expectedCloudConfiguration);
292
293         AAITreeNode expectedVfModule = new AAITreeNode();
294         expectedVfModule.setId("2cb6d41e-2bef-4cb2-80ce-c7815bcdcf4e");
295         expectedVfModule.setName("dyh3brarf8000v_base");
296         expectedVfModule.setOrchestrationStatus("Active");
297         expectedVfModule.setModelInvariantId("3ecca473-b0c0-46ae-b0b7-bd2969d8b79f");
298         expectedVfModule.setModelVersionId("5c35b764-e266-4498-af87-a88c4ba92dc4");
299         expectedVfModule.setModelCustomizationId("06b4ece0-f6f8-4003-b445-653418292101");
300         expectedVfModule.setType(NodeType.VF_MODULE);
301         expectedVfModule.setInMaint(false);
302         expectedVfModule.setCloudConfiguration(expectedCloudConfiguration);
303
304         expectedVnfNode.addChildren(ImmutableList.of(expectedVfModule));
305
306         buildNodeAndAssert(mockedAaiGetVnfResponse, expectedVnfNode, NodeType.GENERIC_VNF);
307     }
308
309     @NotNull
310     public static AAITreeNode createExpectedVnfTreeNode(CloudConfiguration expectedCloudConfiguration) {
311         AAITreeNode expectedVnfNode = new AAITreeNode();
312         expectedVnfNode.setId("9a7a4dc1-8e5f-43fe-a360-7734c5f51382");
313         expectedVnfNode.setName("dyh3brarf8000v");
314         expectedVnfNode.setOrchestrationStatus("Active");
315         expectedVnfNode.setModelInvariantId("b711997f-36b3-4a9b-8b37-71a0fc2ebd6d");
316         expectedVnfNode.setModelVersionId("7f23e4f7-e44c-44df-b066-4cedc6950bfe");
317         expectedVnfNode.setModelCustomizationId("401350be-0f56-481c-86d8-f32d573fec26");
318         expectedVnfNode.setType(NodeType.GENERIC_VNF);
319         expectedVnfNode.setInMaint(true);
320         expectedVnfNode.setProvStatus("PREPROV");
321         expectedVnfNode.setCloudConfiguration(expectedCloudConfiguration);
322         return expectedVnfNode;
323     }
324
325     @DataProvider
326     public static Object[][] isArrayDataProvider() {
327         return new Object[][] {
328                 {"Json Array", buildArrayJson(NodeType.GENERIC_VNF), true},
329                 {"Json Object", buildOneLevelJson(NodeType.GENERIC_VNF), false},
330                 {"Json Array with another node type", buildArrayJson(NodeType.SERVICE_INSTANCE), false},
331                 {"null json", null, false}
332         };
333     }
334
335     @Test(dataProvider = "isArrayDataProvider")
336     public void IsArrayType(String description, JsonNode jsonNode, boolean expectedResult) {
337         boolean isArray = aaiTreeNodeBuilder.isArray(jsonNode, NodeType.GENERIC_VNF);
338         assertEquals(expectedResult, isArray);
339     }
340
341     @Test
342     public void jsonToAaiNodeTest() {
343         NodeType nodeType = NodeType.SERVICE_INSTANCE;
344         JsonNode node = buildOneLevelJson(nodeType);
345         ConcurrentSkipListSet<AAITreeNode> nodesAccumulator = new ConcurrentSkipListSet<>(comparing(AAITreeNode::getUniqueNodeKey));
346
347         AAITreeNode aaiTreeNode = aaiTreeNodeBuilder.createAaiNode(nodeType, node, nodesAccumulator);
348
349         assertEquals("any-instance-id", aaiTreeNode.getId());
350         assertEquals("any-instance-name", aaiTreeNode.getName());
351         assertTrue(nodesAccumulator.contains(aaiTreeNode));
352     }
353
354     @Test
355     public void getNextLevelInPathsTreeTest() {
356         Tree<AAIServiceTree.AaiRelationship> firstLevelTree = getPathsTree();
357
358         Tree<AAIServiceTree.AaiRelationship> secondLevelTree = aaiTreeNodeBuilder.getNextLevelInPathsTree(firstLevelTree, NodeType.GENERIC_VNF.getType());
359         assertEquals(NodeType.GENERIC_VNF.getType(), secondLevelTree.getRootValue().type);
360
361         Tree<AAIServiceTree.AaiRelationship> thirdLevelTree = aaiTreeNodeBuilder.getNextLevelInPathsTree(secondLevelTree, NodeType.INSTANCE_GROUP.getType());
362         assertEquals(NodeType.INSTANCE_GROUP.getType(), thirdLevelTree.getRootValue().type);
363     }
364
365     @Test
366     public void getNextLevelInPathsTreeTest_givenIrrelevantNode_expectedNull() {
367         Tree<AAIServiceTree.AaiRelationship> pathsTree = getPathsTree();
368
369         Tree<AAIServiceTree.AaiRelationship> subTree = aaiTreeNodeBuilder.getNextLevelInPathsTree(pathsTree, NodeType.INSTANCE_GROUP.getType());
370
371         assertNull(subTree);
372     }
373
374     @Test
375     public void getRelationships_given2Relationships_expect1filtered() {
376         NodeType firstRelationship = NodeType.GENERIC_VNF;
377         NodeType secondRelationship = NodeType.INSTANCE_GROUP;
378         JsonNode jsonNode = buildOneLevelJson(NodeType.SERVICE_INSTANCE, firstRelationship, secondRelationship);
379
380         List<Relationship> relationships = aaiTreeNodeBuilder.getFilteredRelationships(jsonNode, getPathsTree());
381
382         assertEquals(1, relationships.size());
383         assertEquals(firstRelationship.getType(), relationships.get(0).getRelatedTo());
384     }
385
386     @Test
387     public void getRelationships_givenNoRelationships_expectedEmptyListTest() {
388         JsonNode jsonNode = buildOneLevelJson(NodeType.SERVICE_INSTANCE);
389
390         List<Relationship> relationships = aaiTreeNodeBuilder.getFilteredRelationships(jsonNode, getPathsTree());
391
392         assertThat(relationships, is(empty()));
393     }
394
395     @Test
396     public void getRelationships_given2RelationshipsNotExistInTreePaths_expectAllFiltered() {
397         NodeType firstRelationship = NodeType.CONFIGURATION;
398         NodeType secondRelationship = NodeType.INSTANCE_GROUP;
399         JsonNode jsonNode = buildOneLevelJson(NodeType.SERVICE_INSTANCE, firstRelationship, secondRelationship);
400
401         List<Relationship> relationships = aaiTreeNodeBuilder.getFilteredRelationships(jsonNode, getPathsTree());
402
403         assertThat(relationships, is(empty()));
404     }
405
406     @Test
407     public void aggregateAllOtherPropertiesTest() {
408         NodeType nodeType = NodeType.SERVICE_INSTANCE;
409         JsonNode jsonNode = buildOneLevelJson(nodeType, NodeType.GENERIC_VNF, NodeType.GENERIC_VNF);
410         ((ObjectNode) jsonNode).put("nf-role", "any-value");
411
412         Map<String, Object> additionalProps = aaiTreeNodeBuilder.aggregateAllOtherProperties(jsonNode, nodeType);
413         assertThat(additionalProps, is(ImmutableMap.of(
414                 "nf-role", "any-value")));
415     }
416
417     @Test
418     public void parseNodeAndFilterRelationshipsTest() {
419         NodeType nodeType = NodeType.SERVICE_INSTANCE;
420         JsonNode jsonNode = buildOneLevelJson(NodeType.SERVICE_INSTANCE, NodeType.GENERIC_VNF, NodeType.NETWORK, NodeType.VF_MODULE);
421         ConcurrentSkipListSet<AAITreeNode> nodesAccumulator = new ConcurrentSkipListSet<>(comparing(AAITreeNode::getUniqueNodeKey));
422
423         Pair<AAITreeNode, List<Relationship>> resultNode = aaiTreeNodeBuilder.parseNodeAndFilterRelationships(jsonNode, nodeType,
424                 nodesAccumulator, getPathsTree());
425
426         assertEquals(nodeType, resultNode.getKey().getType());
427         assertEquals(2, resultNode.getValue().size());
428         assertEquals(NodeType.GENERIC_VNF.getType(), resultNode.getValue().get(0).getRelatedTo());
429         assertEquals(NodeType.NETWORK.getType(), resultNode.getValue().get(1).getRelatedTo());
430     }
431
432     @Test(expectedExceptions = GenericUncheckedException.class ,expectedExceptionsMessageRegExp = "AAI node fetching failed.")
433     public void fetchChildrenAsyncTest_given2children_expected1Ok1Timeout() {
434         ConcurrentSkipListSet<AAITreeNode> nodesAccumulator = new ConcurrentSkipListSet<>(comparing(AAITreeNode::getUniqueNodeKey));
435         ExecutorService threadPool = Executors.newFixedThreadPool(5);
436
437         AAITreeNode rootNode = createExpectedGroupNode();
438         JsonNode relationshipJson = getRelationships(NodeType.GENERIC_VNF, NodeType.NETWORK);
439         List<Relationship> relationships = mapper.convertValue(relationshipJson, RelationshipList.class).getRelationship();
440
441         when(aaiClientMock.typedAaiRest(Unchecked.toURI(relationships.get(0).getRelatedLink()), JsonNode.class, null, HttpMethod.GET, false))
442                 .thenReturn(buildOneLevelJson(NodeType.GENERIC_VNF));
443
444         when(aaiClientMock.typedAaiRest(Unchecked.toURI(relationships.get(1).getRelatedLink()), JsonNode.class, null, HttpMethod.GET, false))
445                 .thenAnswer((Answer<JsonNode>) invocation -> {
446                     Thread.sleep(2000);
447                     return buildOneLevelJson(NodeType.NETWORK);
448                 });
449
450         aaiTreeNodeBuilder.fetchChildrenAsync(threadPool, nodesAccumulator, rootNode, relationships, getPathsTree(), 1);
451
452         assertEquals(2, rootNode.getChildren().size());
453         assertEquals(NodeType.GENERIC_VNF, rootNode.getChildren().get(0).getType());
454         assertEquals(NodeType.NETWORK, rootNode.getChildren().get(1).getType());
455     }
456
457     @DataProvider
458     public Object[][] testIsListOfKeyResultsDataProvider() {
459         return new Object[][]{
460                 {"Node has results with several values",
461                         "{\"results\":[{\"l3-network\":{}},{\"l3-network\":{}},{\"l3-network\":{}}]}",
462                         true},
463                 {"Node has results with no values",
464                         "{\"results\":[]}",
465                         true},
466                 {"Node has results, but it isn't an array",
467                         "{\"results\":{\"some-field\":{}}}",
468                         false},
469                 {"Node doesn't have results",
470                         "{\"l3-network\":[{},{}]}",
471                         false},
472                 {"Node is null",
473                         "null",
474                         false},
475         };
476     }
477
478     @Test(dataProvider = "testIsListOfKeyResultsDataProvider")
479     public void testIsListOfKeyResults(String testCase, String input, boolean expectedResult) throws IOException {
480         assertEquals(testCase + ": " + input,
481                 expectedResult, aaiTreeNodeBuilder.isListOfKeyResults(new ObjectMapper().readTree(input)));
482     }
483
484     private Tree<AAIServiceTree.AaiRelationship> getPathsTree() {
485         Tree<AAIServiceTree.AaiRelationship> pathsTree = new Tree<>(new AAIServiceTree.AaiRelationship(NodeType.SERVICE_INSTANCE));
486         pathsTree.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.INSTANCE_GROUP));
487         pathsTree.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.NETWORK));
488
489         return pathsTree;
490     }
491
492     private static JsonNode buildOneLevelJson(NodeType nodeType, NodeType...relationships) {
493         ObjectNode objectNode = mapper.createObjectNode();
494         objectNode.put(nodeType.getId(), "any-instance-id");
495         objectNode.put(nodeType.getName(), "any-instance-name");
496         if (relationships.length > 0 ) {
497             objectNode.putPOJO("relationship-list", getRelationships(relationships));
498         }
499         return objectNode;
500     }
501
502     private static JsonNode buildArrayJson(NodeType nodeType) {
503         ObjectNode objectNode = mapper.createObjectNode();
504         ArrayNode arrayNode = objectNode.putArray(nodeType.getType());
505         arrayNode.add(buildOneLevelJson(nodeType));
506         arrayNode.add(buildOneLevelJson(nodeType));
507
508         return objectNode;
509     }
510
511     private static JsonNode getRelationship(String nodeType) {
512         ObjectNode relationship = mapper.createObjectNode();
513         relationship.put("related-to", nodeType);
514         relationship.put("relationship-label", "org.onap.relationships.inventory.ComposedOf");
515         relationship.put("related-link", "/aai/v12/network/" + nodeType + "s/" + nodeType + "/cf6f60cd-808d-44e6-978b-c663e00dba8d");
516         return relationship;
517     }
518
519     private static JsonNode getRelationships(NodeType...nodeTypes) {
520         ObjectNode relationshipList = mapper.createObjectNode();
521         ArrayNode relationships = relationshipList.putArray("relationship");
522
523         for (NodeType nodeType: nodeTypes) {
524             relationships.add(getRelationship(nodeType.getType()));
525         }
526
527         return relationshipList;
528     }
529
530 }