/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.atlas.repository.graph; import org.apache.atlas.AtlasException; import org.apache.atlas.TestOnlyModule; import org.apache.atlas.TestUtils; import org.apache.atlas.repository.graph.GraphHelper.VertexInfo; import org.apache.atlas.repository.graphdb.AtlasEdge; import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.services.MetadataService; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.typesystem.ITypedReferenceableInstance; import org.apache.atlas.typesystem.Referenceable; import org.apache.atlas.typesystem.TypesDef; import org.apache.atlas.typesystem.exception.TypeNotFoundException; import org.apache.atlas.typesystem.json.InstanceSerialization; import org.apache.atlas.typesystem.json.TypesSerialization; import org.apache.atlas.typesystem.types.ClassType; import org.apache.atlas.typesystem.types.Multiplicity; import org.apache.atlas.typesystem.types.TypeSystem; import org.codehaus.jettison.json.JSONArray; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Guice; import org.testng.annotations.Test; import javax.inject.Inject; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import static org.testng.Assert.*; @Guice(modules = TestOnlyModule.class) public class GraphHelperTest { @DataProvider(name = "encodeDecodeTestData") private Object[][] createTestData() { return new Object[][]{ {"hivedb$", "hivedb_d"}, {"hivedb", "hivedb"}, {"{hivedb}", "_ohivedb_c"}, {"%hivedb}", "_phivedb_c"}, {"\"hivedb\"", "_qhivedb_q"}, {"\"$%{}", "_q_d_p_o_c"}, {"", ""}, {" ", " "}, {"\n\r", "\n\r"}, {null, null} }; } @Inject private MetadataService metadataService; @Inject private GraphBackedMetadataRepository repositoryService; private TypeSystem typeSystem; @Inject private AtlasTypeRegistry typeRegistry; @BeforeClass public void setUp() throws Exception { typeSystem = TypeSystem.getInstance(); typeSystem.reset(); new GraphBackedSearchIndexer(typeRegistry); TypesDef typesDef = TestUtils.defineHiveTypes(); try { metadataService.getTypeDefinition(TestUtils.TABLE_TYPE); } catch (TypeNotFoundException e) { metadataService.createType(TypesSerialization.toJson(typesDef)); } TestUtils.defineDeptEmployeeTypes(typeSystem); } @AfterClass public void tearDown() { AtlasGraphProvider.cleanup(); } @Test public void testGetInstancesByUniqueAttributes() throws Exception { GraphHelper helper = GraphHelper.getInstance(); List<ITypedReferenceableInstance> instances = new ArrayList<>(); List<String> guids = new ArrayList<>(); TypeSystem ts = TypeSystem.getInstance(); ClassType dbType = ts.getDataType(ClassType.class, TestUtils.DATABASE_TYPE); for(int i = 0; i < 10; i++) { Referenceable db = TestUtils.createDBEntity(); String guid = createInstance(db); ITypedReferenceableInstance instance = convert(db, dbType); instances.add(instance); guids.add(guid); } //lookup vertices via getVertexForInstanceByUniqueAttributes List<AtlasVertex> vertices = helper.getVerticesForInstancesByUniqueAttribute(dbType, instances); assertEquals(instances.size(), vertices.size()); //assert vertex matches the vertex we get through getVertexForGUID for(int i = 0; i < instances.size(); i++) { String guid = guids.get(i); AtlasVertex foundVertex = vertices.get(i); AtlasVertex expectedVertex = helper.getVertexForGUID(guid); assertEquals(foundVertex, expectedVertex); } } @Test public void testGetVerticesForGUIDSWithDuplicates() throws Exception { ITypedReferenceableInstance hrDept = TestUtils.createDeptEg1(TypeSystem.getInstance()); List<String> result = repositoryService.createEntities(hrDept).getCreatedEntities(); String guid = result.get(0); Map<String, AtlasVertex> verticesForGUIDs = GraphHelper.getInstance().getVerticesForGUIDs(Arrays.asList(guid, guid)); Assert.assertEquals(verticesForGUIDs.size(), 1); Assert.assertTrue(verticesForGUIDs.containsKey(guid)); } @Test public void testGetCompositeGuidsAndVertices() throws Exception { ITypedReferenceableInstance hrDept = TestUtils.createDeptEg1(typeSystem); List<String> createdGuids = repositoryService.createEntities(hrDept).getCreatedEntities(); String deptGuid = null; Set<String> expectedGuids = new HashSet<>(); for (String guid : createdGuids) { ITypedReferenceableInstance entityDefinition = repositoryService.getEntityDefinition(guid); expectedGuids.add(guid); if (entityDefinition.getId().getTypeName().equals(TestUtils.DEPARTMENT_TYPE)) { deptGuid = guid; } } AtlasVertex deptVertex = GraphHelper.getInstance().getVertexForGUID(deptGuid); Set<VertexInfo> compositeVertices = GraphHelper.getInstance().getCompositeVertices(deptVertex); HashMap<String, VertexInfo> verticesByGuid = new HashMap<>(); for (VertexInfo vertexInfo: compositeVertices) { verticesByGuid.put(vertexInfo.getGuid(), vertexInfo); } // Verify compositeVertices has entries for all expected guids. Assert.assertEquals(compositeVertices.size(), expectedGuids.size()); for (String expectedGuid : expectedGuids) { Assert.assertTrue(verticesByGuid.containsKey(expectedGuid)); } } @Test(dataProvider = "encodeDecodeTestData") public void testEncodeDecode(String str, String expectedEncodedStr) throws Exception { String encodedStr = GraphHelper.encodePropertyKey(str); assertEquals(encodedStr, expectedEncodedStr); String decodedStr = GraphHelper.decodePropertyKey(encodedStr); assertEquals(decodedStr, str); } @Test public void testGetOutgoingEdgesByLabel() throws Exception { AtlasGraph graph = TestUtils.getGraph(); AtlasVertex v1 = graph.addVertex(); AtlasVertex v2 = graph.addVertex(); graph.addEdge(v1, v2, "l1"); graph.addEdge(v1, v2, "l2"); Iterator<AtlasEdge> iterator = GraphHelper.getInstance().getOutGoingEdgesByLabel(v1, "l1"); assertTrue(iterator.hasNext()); assertTrue(iterator.hasNext()); assertNotNull(iterator.next()); assertNull(iterator.next()); assertFalse(iterator.hasNext()); assertFalse(iterator.hasNext()); } private ITypedReferenceableInstance convert(Referenceable instance, ClassType type) throws AtlasException { return type.convert(instance, Multiplicity.REQUIRED); } private String createInstance(Referenceable entity) throws Exception { TestUtils.resetRequestContext(); String entityjson = InstanceSerialization.toJson(entity, true); JSONArray entitiesJson = new JSONArray(); entitiesJson.put(entityjson); List<String> guids = metadataService.createEntities(entitiesJson.toString()).getCreatedEntities(); if (guids != null && guids.size() > 0) { return guids.get(guids.size() - 1); } return null; } }