1 package org.onap.aai.sparky.viewandinspect.services;
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertNotNull;
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;
12 import java.util.concurrent.ExecutorService;
14 import javax.inject.Inject;
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.entity.ActiveInventoryNode;
38 import org.onap.aai.sparky.viewandinspect.entity.QueryParams;
39 import org.onap.aai.sparky.viewandinspect.enumeration.NodeProcessingState;
40 import org.springframework.test.context.ContextConfiguration;
41 import org.springframework.test.context.TestPropertySource;
42 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
46 @RunWith(SpringJUnit4ClassRunner.class)
47 @TestPropertySource(properties = {
48 "schemaIngestPropLoc = src/test/resources/oxm-reader/schema-ingest-single-oxm.properties" })
49 @ContextConfiguration(locations = { "classpath:oxm-reader/oxm-reader-bean.xml" })
52 public class BaseVisualizationContextTest {
54 private static SecureRandom secureRandom = new SecureRandom();
55 private static Logger LOG =
56 LoggerFactory.getInstance().getLogger(BaseVisualizationContextTest.class);
58 private BaseVisualizationContext baseVisualizationContext;
59 private ExecutorService aaiExecutorService;
60 private VisualizationConfigs visualizationConfig;
62 private ActiveInventoryAdapter aaiAdapter;
63 private RestEndpointConfig aaiRestEndPointConfig;
66 private OxmEntityLookup oxmEntityLookup;
69 public void init() throws Exception {
71 aaiExecutorService = NodeUtils.createNamedExecutor("SLNC-WORKER", 5, LOG);
72 visualizationConfig = new VisualizationConfigs();
74 ArrayList<String> shallowEntities = new ArrayList<String>();
75 shallowEntities.add("cloud-region");
77 visualizationConfig.setShallowEntities(shallowEntities);
78 visualizationConfig.setMaxSelfLinkTraversalDepth(2);
81 aaiAdapter = Mockito.mock(ActiveInventoryAdapter.class);
83 aaiRestEndPointConfig = new RestEndpointConfig();
84 aaiRestEndPointConfig.setNumRequestRetries(5);
86 Mockito.when(aaiAdapter.getEndpointConfig()).thenReturn(aaiRestEndPointConfig);
88 MdcContext.initialize("" + secureRandom.nextLong(), "AAI-UI", "", "partner-name",
91 // all our resources are prefixed already, so the repairSelfLink shouldn't do anything to the link
92 Mockito.when(aaiAdapter.repairSelfLink(Matchers.contains(""))).thenReturn("");
97 private Matcher<List<String>> listContainsValue(String expectedValue) {
98 return new StringCollectionContainsMatcher(expectedValue);
103 public void validateBasicConstruction() throws Exception {
105 long contextId = secureRandom.nextLong();
107 baseVisualizationContext = new BaseVisualizationContext(contextId, aaiAdapter,
108 aaiExecutorService, visualizationConfig, oxmEntityLookup);
110 assertEquals(contextId, baseVisualizationContext.getContextId());
115 public void validateSmallGraphAssembly() throws Exception {
118 * We have a tiny graph that we will validate assembly of:
120 * <li>customer -> tenant
121 * <li>customer -> service-subscription
122 * <li>service-subscription -> service-instance-1
123 * <li>service-subscription -> service-instance-2
125 * At the end of this success path, we should have 5 nodes in the node cache. Once we have this
126 * flow we can experiment with error paths involving resource download failures to ensure graph
127 * nodes are in the correct state and that expected nodes are successfully represented in the
131 long contextId = secureRandom.nextLong();
133 baseVisualizationContext = new BaseVisualizationContext(contextId, aaiAdapter,
134 aaiExecutorService, visualizationConfig, oxmEntityLookup);
136 SearchableEntity searchableEntity = new SearchableEntity();
137 String customerSelfLink =
138 "https://server.proxy:8443/aai/v11/business/customers/customer/customer-4";
139 String customerNodeId = NodeUtils.generateUniqueShaDigest(customerSelfLink);
141 searchableEntity.setId(customerNodeId);
142 searchableEntity.setEntityType("customer");
143 searchableEntity.setEntityPrimaryKeyValue("customer-4");
144 searchableEntity.setLink(customerSelfLink);
146 QueryParams queryParams = new QueryParams();
147 queryParams.setSearchTargetNodeId(customerNodeId);
148 queryParams.setSearchTargetPrimaryKeyValues("customer-4");
150 // aai customer resource dip
153 .when(aaiAdapter.queryActiveInventoryWithRetries(Matchers.contains("customer-4"),
154 Mockito.anyString(), Mockito.anyInt()))
155 .thenReturn(new OperationResult(200, TestResourceLoader
156 .getTestResourceDataJson("/sync/aai/aai-resources/customer/customer-4.json")));
158 // aai tenant resource dip
161 .when(aaiAdapter.queryActiveInventoryWithRetries(Matchers.contains("tenant/tenant-1"),
162 Mockito.anyString(), Mockito.anyInt()))
163 .thenReturn(new OperationResult(200, TestResourceLoader
164 .getTestResourceDataJson("/sync/aai/aai-resources/tenant/tenant-1.json")));
166 // generic-queries for service-subscription
169 .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-subscription"),
171 listContainsValue("service-subscription.service-type:service-subscription-2"))))
173 "https://server.proxy:8443/aai/v11/search/generic-query/service-subscription-2");
176 .when(aaiAdapter.queryActiveInventoryWithRetries(
177 Matchers.contains("generic-query/service-subscription-2"), Mockito.anyString(),
179 .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
180 "/sync/aai/aai-traversal/generic-query/service-subscription/service-subscription-2.json")));
182 // generic-queries for service-instance-1
185 .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
186 Matchers.argThat(listContainsValue("service-instance-id:service-instance-54"))))
188 "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-id/service-instance-54");
191 .when(aaiAdapter.queryActiveInventoryWithRetries(
192 Matchers.contains("generic-query/service-instance-id/service-instance-54"),
193 Mockito.anyString(), Mockito.anyInt()))
194 .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
195 "/sync/aai/aai-traversal/generic-query/service-instance/service-instance-54.json")));
197 // generic-queries for service-instance-2
200 .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
201 Matchers.argThat(listContainsValue("service-instance-id:service-instance-55"))))
203 "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-id/service-instance-55");
206 .when(aaiAdapter.queryActiveInventoryWithRetries(
207 Matchers.contains("generic-query/service-instance-id/service-instance-55"),
208 Mockito.anyString(), Mockito.anyInt()))
209 .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
210 "/sync/aai/aai-traversal/generic-query/service-instance/service-instance-55.json")));
216 baseVisualizationContext.processSelfLinks(searchableEntity, queryParams);
219 * validation can be in the form of validating nodes + relationships from the node cache
220 * baseVisualizationContext.getNodeCache();
223 Map<String, ActiveInventoryNode> nodeCache = baseVisualizationContext.getNodeCache();
225 assertEquals(5, nodeCache.size());
226 assertNotNull(nodeCache.get(customerNodeId));
227 assertEquals("customer", nodeCache.get(customerNodeId).getEntityType());
229 // verify node collection nodes
231 ActiveInventoryNode customerNode =
232 nodeCache.get("da4101ad19b3c380a1c12ffeda8ab390e1489fb4a22a392c9a1939db63c3dec5");
233 ActiveInventoryNode ssNode =
234 nodeCache.get("f4ceaf19459993c4fc9438a7579dd20d786109f4455e38682c579045b7ae615e");
235 ActiveInventoryNode tenantNode =
236 nodeCache.get("4735439b29e446b339535668238076e4b392eaa3eec218936e12f735179bc55e");
237 ActiveInventoryNode s1 =
238 nodeCache.get("f975ab453b142197af5d0173e0a9cf2aa22d10502f8ad655c8d17de81b066e8f");
239 ActiveInventoryNode s2 =
240 nodeCache.get("de77ef8f76dd6f19662b163527ff839891b9596cac655e3143fdd7ad39e2e4e3");
242 assertNotNull(customerNode);
243 assertNotNull(ssNode);
244 assertNotNull(tenantNode);
248 // verify node depths
250 assertEquals(0, customerNode.getNodeDepth());
251 assertEquals(1, ssNode.getNodeDepth());
254 * I think there is a bug in the way the node depth is represented due to the enforcement of
255 * bidirectional links being disabled. We may have to circle back to this behavior at some point
256 * and re-verify that the behavior works properly.
259 assertEquals(2, tenantNode.getNodeDepth());
260 assertEquals(2, s1.getNodeDepth());
261 assertEquals(2, s2.getNodeDepth());
263 // verify node states
265 assertEquals(NodeProcessingState.READY, customerNode.getState());
266 assertEquals(NodeProcessingState.READY, ssNode.getState());
269 * these nodes have a NEIGHBORS_UNPROCESSED state because the max traversal depth was hit before
270 * processing all the nested relationships. I think what we should look at is advancing the
271 * state to READY if in fact there are no relationships to process, which I think could be the
274 assertEquals(NodeProcessingState.NEIGHBORS_UNPROCESSED, tenantNode.getState());
275 assertEquals(NodeProcessingState.NEIGHBORS_UNPROCESSED, s1.getState());
276 assertEquals(NodeProcessingState.NEIGHBORS_UNPROCESSED, s2.getState());
280 protected DynamicJAXBContext createVersionedOxm() {
281 Map<String, Object> properties = new HashMap<>();
282 ClassLoader classLoader = null;
283 InputStream iStream = classLoader.getResourceAsStream("example/resources/eclipselink/eclipselink-oxm.xml");
285 properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, iStream);
287 return DynamicJAXBContextFactory.createContextFromOXM(this.getClass().getClassLoader(), properties);
288 } catch (Exception e) {