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