package org.onap.aai.sparky.viewandinspect.services; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.security.SecureRandom; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; import org.hamcrest.Matcher; import org.junit.Before; import org.junit.Test; import org.mockito.Matchers; import org.mockito.Mockito; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; import org.onap.aai.cl.mdc.MdcContext; import org.onap.aai.restclient.client.OperationResult; import org.onap.aai.sparky.config.oxm.OxmEntityLookup; import org.onap.aai.sparky.config.oxm.OxmModelLoader; import org.onap.aai.sparky.config.oxm.OxmModelProcessor; import org.onap.aai.sparky.dal.ActiveInventoryAdapter; import org.onap.aai.sparky.dal.rest.config.RestEndpointConfig; import org.onap.aai.sparky.sync.entity.SearchableEntity; import org.onap.aai.sparky.util.NodeUtils; import org.onap.aai.sparky.util.StringCollectionContainsMatcher; import org.onap.aai.sparky.util.TestResourceLoader; import org.onap.aai.sparky.viewandinspect.config.VisualizationConfigs; import org.onap.aai.sparky.viewandinspect.entity.ActiveInventoryNode; import org.onap.aai.sparky.viewandinspect.entity.QueryParams; import org.onap.aai.sparky.viewandinspect.enumeration.NodeProcessingState; public class BaseVisualizationContextTest { private static SecureRandom secureRandom = new SecureRandom(); private static Logger LOG = LoggerFactory.getInstance().getLogger(BaseVisualizationContextTest.class); private BaseVisualizationContext baseVisualizationContext; private ExecutorService aaiExecutorService; private VisualizationConfigs visualizationConfig; private OxmEntityLookup oxmEntityLookup; private ActiveInventoryAdapter aaiAdapter; private RestEndpointConfig aaiRestEndPointConfig; @Before public void init() throws Exception { aaiExecutorService = NodeUtils.createNamedExecutor("SLNC-WORKER", 5, LOG); visualizationConfig = new VisualizationConfigs(); ArrayList shallowEntities = new ArrayList(); shallowEntities.add("cloud-region"); visualizationConfig.setShallowEntities(shallowEntities); visualizationConfig.setMaxSelfLinkTraversalDepth(2); oxmEntityLookup = new OxmEntityLookup(); aaiAdapter = Mockito.mock(ActiveInventoryAdapter.class); Set processors = new HashSet(); processors.add(oxmEntityLookup); OxmModelLoader oxmModelLoader = new OxmModelLoader(-1, processors); oxmModelLoader.loadLatestOxmModel(); aaiRestEndPointConfig = new RestEndpointConfig(); aaiRestEndPointConfig.setNumRequestRetries(5); Mockito.when(aaiAdapter.getEndpointConfig()).thenReturn(aaiRestEndPointConfig); MdcContext.initialize("" + secureRandom.nextLong(), "AAI-UI", "", "partner-name", "localhost:4242"); // all our resources are prefixed already, so the repairSelfLink shouldn't do anything to the link Mockito.when(aaiAdapter.repairSelfLink(Matchers.contains(""))).thenReturn(""); } private Matcher> listContainsValue(String expectedValue) { return new StringCollectionContainsMatcher(expectedValue); } @Test public void validateBasicConstruction() throws Exception { long contextId = secureRandom.nextLong(); baseVisualizationContext = new BaseVisualizationContext(contextId, aaiAdapter, aaiExecutorService, visualizationConfig, oxmEntityLookup); assertEquals(contextId, baseVisualizationContext.getContextId()); } @Test public void validateSmallGraphAssembly() throws Exception { /** * We have a tiny graph that we will validate assembly of: * *
  • customer -> tenant *
  • customer -> service-subscription *
  • service-subscription -> service-instance-1 *
  • service-subscription -> service-instance-2 * * At the end of this success path, we should have 5 nodes in the node cache. Once we have this * flow we can experiment with error paths involving resource download failures to ensure graph * nodes are in the correct state and that expected nodes are successfully represented in the * cache. */ long contextId = secureRandom.nextLong(); baseVisualizationContext = new BaseVisualizationContext(contextId, aaiAdapter, aaiExecutorService, visualizationConfig, oxmEntityLookup); SearchableEntity searchableEntity = new SearchableEntity(); String customerSelfLink = "https://server.proxy:8443/aai/v11/business/customers/customer/customer-4"; String customerNodeId = NodeUtils.generateUniqueShaDigest(customerSelfLink); searchableEntity.setId(customerNodeId); searchableEntity.setEntityType("customer"); searchableEntity.setEntityPrimaryKeyValue("customer-4"); searchableEntity.setLink(customerSelfLink); QueryParams queryParams = new QueryParams(); queryParams.setSearchTargetNodeId(customerNodeId); queryParams.setSearchTargetPrimaryKeyValues("customer-4"); // aai customer resource dip Mockito .when(aaiAdapter.queryActiveInventoryWithRetries( Matchers.contains("customer-4"), Mockito.anyString(), Mockito.anyInt())) .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson( "/sync/aai/aai-resources/customer/customer-4.json"))); // aai tenant resource dip Mockito .when(aaiAdapter.queryActiveInventoryWithRetries( Matchers.contains("tenant/tenant-1"), Mockito.anyString(), Mockito.anyInt())) .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson( "/sync/aai/aai-resources/tenant/tenant-1.json"))); // generic-queries for service-subscription Mockito .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-subscription"), Matchers.argThat(listContainsValue("service-subscription.service-type:service-subscription-2")))) .thenReturn( "https://server.proxy:8443/aai/v11/search/generic-query/service-subscription-2"); Mockito .when(aaiAdapter.queryActiveInventoryWithRetries( Matchers.contains("generic-query/service-subscription-2"), Mockito.anyString(), Mockito.anyInt())) .thenReturn(new OperationResult(200, TestResourceLoader .getTestResourceDataJson("/sync/aai/aai-traversal/generic-query/service-subscription/service-subscription-2.json"))); // generic-queries for service-instance-1 Mockito .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"), Matchers.argThat( listContainsValue("service-instance-id:service-instance-54")))) .thenReturn( "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-id/service-instance-54"); Mockito .when(aaiAdapter.queryActiveInventoryWithRetries( Matchers .contains("generic-query/service-instance-id/service-instance-54"), Mockito.anyString(), Mockito.anyInt())) .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson( "/sync/aai/aai-traversal/generic-query/service-instance/service-instance-54.json"))); // generic-queries for service-instance-2 Mockito .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"), Matchers.argThat( listContainsValue("service-instance-id:service-instance-55")))) .thenReturn( "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-id/service-instance-55"); Mockito .when(aaiAdapter.queryActiveInventoryWithRetries( Matchers .contains("generic-query/service-instance-id/service-instance-55"), Mockito.anyString(), Mockito.anyInt())) .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson( "/sync/aai/aai-traversal/generic-query/service-instance/service-instance-55.json"))); // start the test baseVisualizationContext.processSelfLinks(searchableEntity, queryParams); /* * validation can be in the form of validating nodes + relationships from the node cache * baseVisualizationContext.getNodeCache(); */ Map nodeCache = baseVisualizationContext.getNodeCache(); assertEquals(5, nodeCache.size()); assertNotNull(nodeCache.get(customerNodeId)); assertEquals("customer", nodeCache.get(customerNodeId).getEntityType()); // verify node collection nodes ActiveInventoryNode customerNode = nodeCache.get("da4101ad19b3c380a1c12ffeda8ab390e1489fb4a22a392c9a1939db63c3dec5"); ActiveInventoryNode ssNode = nodeCache.get("f4ceaf19459993c4fc9438a7579dd20d786109f4455e38682c579045b7ae615e"); ActiveInventoryNode tenantNode = nodeCache.get("4735439b29e446b339535668238076e4b392eaa3eec218936e12f735179bc55e"); ActiveInventoryNode s1 = nodeCache.get("f975ab453b142197af5d0173e0a9cf2aa22d10502f8ad655c8d17de81b066e8f"); ActiveInventoryNode s2 = nodeCache.get("de77ef8f76dd6f19662b163527ff839891b9596cac655e3143fdd7ad39e2e4e3"); assertNotNull( customerNode ); assertNotNull( ssNode ); assertNotNull( tenantNode ); assertNotNull( s1 ); assertNotNull( s2 ); // verify node depths assertEquals( 0, customerNode.getNodeDepth() ); assertEquals( 1, ssNode.getNodeDepth() ); /* * I think there is a bug in the way the node depth is represented due to the enforcement of * bidirectional links being disabled. We may have to circle back to this behavior at some point * and re-verify that the behavior works properly. */ assertEquals( 2, tenantNode.getNodeDepth() ); assertEquals( 2, s1.getNodeDepth() ); assertEquals( 2, s2.getNodeDepth() ); // verify node states assertEquals( NodeProcessingState.READY, customerNode.getState() ); assertEquals( NodeProcessingState.READY, ssNode.getState() ); /* * these nodes have a NEIGHBORS_UNPROCESSED state because the max traversal depth was hit before * processing all the nested relationships. I think what we should look at is advancing the state * to READY if in fact there are no relationships to process, which I think could be the case * sometimes. */ assertEquals( NodeProcessingState.NEIGHBORS_UNPROCESSED, tenantNode.getState() ); assertEquals( NodeProcessingState.NEIGHBORS_UNPROCESSED, s1.getState() ); assertEquals( NodeProcessingState.NEIGHBORS_UNPROCESSED, s2.getState() ); } }