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) {