9b086c5bfa62b297de37df5f30b031c6119d746f
[aai/sparky-be.git] /
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 Amdocs
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *       http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.aai.sparky.viewandinspect;
23
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertNotNull;
26
27 import java.io.InputStream;
28 import java.security.SecureRandom;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.concurrent.ExecutorService;
34
35 import javax.inject.Inject;
36
37 import org.eclipse.persistence.jaxb.JAXBContextProperties;
38 import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
39 import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
40 import org.hamcrest.Matcher;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.mockito.Matchers;
45 import org.mockito.Mockito;
46 import org.onap.aai.cl.api.Logger;
47 import org.onap.aai.cl.eelf.LoggerFactory;
48 import org.onap.aai.cl.mdc.MdcContext;
49 import org.onap.aai.restclient.client.OperationResult;
50 import org.onap.aai.sparky.config.oxm.OxmEntityLookup;
51 import org.onap.aai.sparky.dal.ActiveInventoryAdapter;
52 import org.onap.aai.sparky.dal.rest.config.RestEndpointConfig;
53 import org.onap.aai.sparky.sync.entity.SearchableEntity;
54 import org.onap.aai.sparky.util.NodeUtils;
55 import org.onap.aai.sparky.util.StringCollectionContainsMatcher;
56 import org.onap.aai.sparky.util.TestResourceLoader;
57 import org.onap.aai.sparky.viewandinspect.config.VisualizationConfigs;
58 import org.onap.aai.sparky.viewandinspect.context.BaseVisualizationContext;
59 import org.onap.aai.sparky.viewandinspect.entity.ActiveInventoryNode;
60 import org.onap.aai.sparky.viewandinspect.entity.QueryParams;
61 import org.onap.aai.sparky.viewandinspect.enumeration.NodeProcessingState;
62 import org.springframework.test.context.ContextConfiguration;
63 import org.springframework.test.context.TestPropertySource;
64 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
65
66
67
68 @RunWith(SpringJUnit4ClassRunner.class)
69 @TestPropertySource(properties = {
70 "schemaIngestPropLoc = src/test/resources/oxm-reader/schema-ingest-single-oxm.properties",
71 "CONFIG_HOME = ./config" })
72 @ContextConfiguration(locations = { "classpath:oxm-reader/oxm-reader-bean.xml" })
73 public class BaseVisualizationContextTest {
74
75   private static SecureRandom secureRandom = new SecureRandom();
76   private static Logger LOG =
77       LoggerFactory.getInstance().getLogger(BaseVisualizationContextTest.class);
78
79   private BaseVisualizationContext baseVisualizationContext;
80   private ExecutorService aaiExecutorService;
81   private VisualizationConfigs visualizationConfig; 
82
83   private ActiveInventoryAdapter aaiAdapter;
84   private RestEndpointConfig aaiRestEndPointConfig; 
85   
86   @Inject
87   private OxmEntityLookup oxmEntityLookup;
88   
89   @Before
90   public void init() throws Exception {
91
92     aaiExecutorService = NodeUtils.createNamedExecutor("SLNC-WORKER", 5, LOG);
93     visualizationConfig = new VisualizationConfigs();
94     
95     ArrayList<String> shallowEntities = new ArrayList<String>();
96     shallowEntities.add("cloud-region");
97     
98     visualizationConfig.setShallowEntities(shallowEntities);
99     visualizationConfig.setMaxSelfLinkTraversalDepth(2); 
100
101
102     aaiAdapter = Mockito.mock(ActiveInventoryAdapter.class);
103
104     aaiRestEndPointConfig = new RestEndpointConfig();
105     aaiRestEndPointConfig.setNumRequestRetries(5);
106     
107     Mockito.when(aaiAdapter.getEndpointConfig()).thenReturn(aaiRestEndPointConfig);
108     
109     MdcContext.initialize("" + secureRandom.nextLong(), "AAI-UI", "", "partner-name",
110         "localhost:4242");
111     
112     // all our resources are prefixed already, so the repairSelfLink shouldn't do anything to the link
113     Mockito.when(aaiAdapter.repairSelfLink(Matchers.contains(""))).thenReturn("");
114
115     
116   }
117
118   private Matcher<List<String>> listContainsValue(String expectedValue) {
119     return new StringCollectionContainsMatcher(expectedValue);
120   }
121
122
123   @Test
124   public void validateBasicConstruction() throws Exception {
125
126     long contextId = secureRandom.nextLong();
127
128     baseVisualizationContext = new BaseVisualizationContext(contextId, aaiAdapter,
129         aaiExecutorService, visualizationConfig, oxmEntityLookup);
130
131     assertEquals(contextId, baseVisualizationContext.getContextId());
132
133   }
134
135   @Test
136   public void validateSmallGraphAssembly() throws Exception {
137
138     /**
139      * We have a tiny graph that we will validate assembly of:
140      * 
141      * <li>customer -> tenant
142      * <li>customer -> service-subscription
143      * <li>service-subscription -> service-instance-1
144      * <li>service-subscription -> service-instance-2
145      * 
146      * At the end of this success path, we should have 5 nodes in the node cache. Once we have this
147      * flow we can experiment with error paths involving resource download failures to ensure graph
148      * nodes are in the correct state and that expected nodes are successfully represented in the
149      * cache.
150      */
151
152     long contextId = secureRandom.nextLong();
153
154     baseVisualizationContext = new BaseVisualizationContext(contextId, aaiAdapter,
155         aaiExecutorService, visualizationConfig, oxmEntityLookup);
156
157     SearchableEntity searchableEntity = new SearchableEntity();
158     String customerSelfLink =
159         "https://server.proxy:8443/aai/v11/business/customers/customer/customer-4";
160     String customerNodeId = NodeUtils.generateUniqueShaDigest(customerSelfLink);
161
162     searchableEntity.setId(customerNodeId);
163     searchableEntity.setEntityType("customer");
164     searchableEntity.setEntityPrimaryKeyValue("customer-4");
165     searchableEntity.setLink(customerSelfLink);
166
167     QueryParams queryParams = new QueryParams();
168     queryParams.setSearchTargetNodeId(customerNodeId);
169     queryParams.setSearchTargetPrimaryKeyValues("customer-4");
170
171     // aai customer resource dip
172
173     Mockito
174         .when(aaiAdapter.queryActiveInventoryWithRetries(Matchers.contains("customer-4"),
175             Mockito.anyString(), Mockito.anyInt(),Mockito.anyString()))
176         .thenReturn(new OperationResult(200, TestResourceLoader
177             .getTestResourceDataJson("/sync/aai/aai-resources/customer/customer-4.json")));
178
179     // aai tenant resource dip
180
181     Mockito
182         .when(aaiAdapter.queryActiveInventoryWithRetries(Matchers.contains("tenant/tenant-1"),
183             Mockito.anyString(), Mockito.anyInt(),Mockito.anyString()))
184         .thenReturn(new OperationResult(200, TestResourceLoader
185             .getTestResourceDataJson("/sync/aai/aai-resources/tenant/tenant-1.json")));
186
187     // generic-queries for service-subscription
188
189     Mockito
190         .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-subscription"),
191             Matchers.argThat(
192                 listContainsValue("service-subscription.service-type:service-subscription-2"))))
193         .thenReturn(
194             "https://server.proxy:8443/aai/v11/search/generic-query/service-subscription-2");
195
196     Mockito
197         .when(aaiAdapter.queryActiveInventoryWithRetries(
198             Matchers.contains("generic-query/service-subscription-2"), Mockito.anyString(),
199             Mockito.anyInt(),Mockito.anyString()))
200         .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
201             "/sync/aai/aai-traversal/generic-query/service-subscription/service-subscription-2.json")));
202
203     // generic-queries for service-instance-1
204
205     Mockito
206         .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
207             Matchers.argThat(listContainsValue("service-instance-id:service-instance-54"))))
208         .thenReturn(
209             "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-id/service-instance-54");
210
211     Mockito
212         .when(aaiAdapter.queryActiveInventoryWithRetries(
213             Matchers.contains("generic-query/service-instance-id/service-instance-54"),
214             Mockito.anyString(), Mockito.anyInt(),Mockito.anyString()))
215         .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
216             "/sync/aai/aai-traversal/generic-query/service-instance/service-instance-54.json")));
217
218     // generic-queries for service-instance-2
219
220     Mockito
221         .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
222             Matchers.argThat(listContainsValue("service-instance-id:service-instance-55"))))
223         .thenReturn(
224             "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-id/service-instance-55");
225
226     Mockito
227         .when(aaiAdapter.queryActiveInventoryWithRetries(
228             Matchers.contains("generic-query/service-instance-id/service-instance-55"),
229             Mockito.anyString(), Mockito.anyInt(),Mockito.anyString()))
230         .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
231             "/sync/aai/aai-traversal/generic-query/service-instance/service-instance-55.json")));
232
233
234
235     // start the test
236
237     baseVisualizationContext.processSelfLinks(searchableEntity, queryParams);
238
239     /*
240      * validation can be in the form of validating nodes + relationships from the node cache
241      * baseVisualizationContext.getNodeCache();
242      */
243
244     Map<String, ActiveInventoryNode> nodeCache = baseVisualizationContext.getNodeCache();
245
246     assertEquals(5, nodeCache.size());
247     assertNotNull(nodeCache.get(customerNodeId));
248     assertEquals("customer", nodeCache.get(customerNodeId).getEntityType());
249
250     // verify node collection nodes
251
252     ActiveInventoryNode customerNode =
253         nodeCache.get("da4101ad19b3c380a1c12ffeda8ab390e1489fb4a22a392c9a1939db63c3dec5");
254     ActiveInventoryNode ssNode =
255         nodeCache.get("f4ceaf19459993c4fc9438a7579dd20d786109f4455e38682c579045b7ae615e");
256     ActiveInventoryNode tenantNode =
257         nodeCache.get("4735439b29e446b339535668238076e4b392eaa3eec218936e12f735179bc55e");
258     ActiveInventoryNode s1 =
259         nodeCache.get("f975ab453b142197af5d0173e0a9cf2aa22d10502f8ad655c8d17de81b066e8f");
260     ActiveInventoryNode s2 =
261         nodeCache.get("de77ef8f76dd6f19662b163527ff839891b9596cac655e3143fdd7ad39e2e4e3");
262
263     assertNotNull(customerNode);
264     assertNotNull(ssNode);
265     assertNotNull(tenantNode);
266     assertNotNull(s1);
267     assertNotNull(s2);
268
269     // verify node depths
270
271     assertEquals(0, customerNode.getNodeDepth());
272     assertEquals(1, ssNode.getNodeDepth());
273
274     /*
275      * I think there is a bug in the way the node depth is represented due to the enforcement of
276      * bidirectional links being disabled. We may have to circle back to this behavior at some point
277      * and re-verify that the behavior works properly.
278      */
279
280     assertEquals(2, tenantNode.getNodeDepth());
281     assertEquals(2, s1.getNodeDepth());
282     assertEquals(2, s2.getNodeDepth());
283
284     // verify node states
285
286     assertEquals(NodeProcessingState.READY, customerNode.getState());
287     assertEquals(NodeProcessingState.READY, ssNode.getState());
288
289     /*
290      * these nodes have a NEIGHBORS_UNPROCESSED state because the max traversal depth was hit before
291      * processing all the nested relationships. I think what we should look at is advancing the
292      * state to READY if in fact there are no relationships to process, which I think could be the
293      * case sometimes.
294      */
295     assertEquals(NodeProcessingState.NEIGHBORS_UNPROCESSED, tenantNode.getState());
296     assertEquals(NodeProcessingState.NEIGHBORS_UNPROCESSED, s1.getState());
297     assertEquals(NodeProcessingState.NEIGHBORS_UNPROCESSED, s2.getState());
298
299   }
300
301   protected DynamicJAXBContext createVersionedOxm() {    
302     Map<String, Object> properties = new HashMap<>(); 
303     ClassLoader classLoader = null;
304     InputStream iStream = classLoader.getResourceAsStream("example/resources/eclipselink/eclipselink-oxm.xml");
305
306     properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, iStream);
307     try{
308     return DynamicJAXBContextFactory.createContextFromOXM(this.getClass().getClassLoader(), properties);
309     } catch (Exception e) {
310       return null;
311     }
312   } 
313
314
315 }