You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ma...@apache.org on 2017/11/10 05:48:17 UTC

[1/5] atlas git commit: ATLAS-2251: restored bunch of deleted tests

Repository: atlas
Updated Branches:
  refs/heads/ATLAS-2251 5f40541b5 -> 042fc5575


http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/webapp/src/test/java/org/apache/atlas/util/RestUtilsTest.java
----------------------------------------------------------------------
diff --git a/webapp/src/test/java/org/apache/atlas/util/RestUtilsTest.java b/webapp/src/test/java/org/apache/atlas/util/RestUtilsTest.java
new file mode 100644
index 0000000..0d4af1e
--- /dev/null
+++ b/webapp/src/test/java/org/apache/atlas/util/RestUtilsTest.java
@@ -0,0 +1,195 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.util;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.*;
+
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
+import org.apache.atlas.model.typedef.AtlasEntityDef;
+import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
+import org.apache.atlas.model.typedef.AtlasTypesDef;
+import org.apache.atlas.repository.Constants;
+import org.apache.atlas.repository.converters.TypeConverterUtil;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1;
+import org.apache.atlas.repository.store.graph.v1.AtlasStructDefStoreV1;
+import org.apache.atlas.repository.store.graph.v1.AtlasTypeDefGraphStoreV1;
+import org.apache.atlas.type.AtlasEntityType;
+import org.apache.atlas.type.AtlasStructType;
+import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
+import org.apache.atlas.type.AtlasType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.atlas.type.AtlasTypeRegistry.AtlasTransientTypeRegistry;
+import org.apache.atlas.typesystem.types.DataTypes.TypeCategory;
+import org.apache.atlas.v1.model.typedef.*;
+import org.apache.atlas.v1.typesystem.types.utils.TypesUtil;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Validates that conversion from V1 to legacy types (and back) is consistent.  This also tests
+ * that the conversion logic in AtlasStructDefStoreV1 is consistent with the conversion logic
+ * in RestUtils.  This tests particularly focuses on composite attributes, since a defect was
+ * found in that area.
+ */
+public class RestUtilsTest {
+
+    @Test(enabled=false)
+    // FIXME: On conversion back to V1, reverse attribute name
+    // "containingDatabase"
+    // in tables attribute in "database" type is lost.  See ATLAS-1528.
+    public void testBidirectonalCompositeMappingConsistent() throws AtlasBaseException {
+
+        ClassTypeDefinition dbV1Type = TypesUtil.createClassTypeDef("database", "", Collections.emptySet(),
+                                           new AttributeDefinition("tables", AtlasBaseTypeDef.getArrayTypeName("table"),
+                                                                   Multiplicity.OPTIONAL, true, "containingDatabase"));
+
+        ClassTypeDefinition tableV1Type = TypesUtil.createClassTypeDef("table", "", Collections.emptySet(),
+                                            new AttributeDefinition("containingDatabase", "database",
+                                                                    Multiplicity.OPTIONAL, false, "tables"));
+
+        testV1toV2toV1Conversion(Arrays.asList(dbV1Type, tableV1Type), new boolean[] { true, false });
+    }
+
+    @Test(enabled=false)
+    // FIXME: On conversion back to V1, reverse attribute name
+    // "containingDatabase" is lost
+    // in "table" attribute in "database".  See ATLAS-1528.
+    public void testBidirectonalNonCompositeMappingConsistent() throws AtlasBaseException {
+        ClassTypeDefinition dbV1Type = TypesUtil.createClassTypeDef("database", "", Collections.emptySet(),
+                                        new AttributeDefinition("tables", AtlasBaseTypeDef.getArrayTypeName("table"),
+                                                                Multiplicity.OPTIONAL, false, "containingDatabase"));
+
+        ClassTypeDefinition tableV1Type = TypesUtil.createClassTypeDef("table", "", Collections.emptySet(),
+                                           new AttributeDefinition("containingDatabase", "database",
+                                                                   Multiplicity.OPTIONAL, false, "tables"));
+
+        testV1toV2toV1Conversion(Arrays.asList(dbV1Type, tableV1Type), new boolean[] { false, false });
+    }
+
+    private AtlasTypeDefGraphStoreV1 makeTypeStore(AtlasTypeRegistry reg) {
+        AtlasTypeDefGraphStoreV1 result = mock(AtlasTypeDefGraphStoreV1.class);
+
+        for (AtlasEntityType type : reg.getAllEntityTypes()) {
+            String      typeName = type.getTypeName();
+            AtlasVertex typeVertex = mock(AtlasVertex.class);
+
+            when(result.isTypeVertex(eq(typeVertex), any(TypeCategory.class))).thenReturn(true);
+            when(typeVertex.getProperty(eq(Constants.TYPE_CATEGORY_PROPERTY_KEY), eq(TypeCategory.class))).thenReturn(TypeCategory.CLASS);
+
+            String attributeListPropertyKey = AtlasGraphUtilsV1.getTypeDefPropertyKey(typeName);
+
+            when(typeVertex.getProperty(eq(attributeListPropertyKey), eq(List.class))).thenReturn(new ArrayList<>(type.getAllAttributes().keySet()));
+
+            for (AtlasAttribute attribute : type.getAllAttributes().values()) {
+                String attributeDefPropertyKey = AtlasGraphUtilsV1.getTypeDefPropertyKey(typeName, attribute.getName());
+                String attributeJson           = AtlasStructDefStoreV1.toJsonFromAttribute(attribute);
+
+                when(typeVertex.getProperty(eq(attributeDefPropertyKey), eq(String.class))).thenReturn(attributeJson);
+            }
+
+            when(result.findTypeVertexByName(eq(typeName))).thenReturn(typeVertex);
+        }
+
+        return result;
+    }
+
+    private AtlasAttributeDef convertToJsonAndBack(AtlasTypeRegistry registry, AtlasStructDef structDef, AtlasAttributeDef attributeDef, boolean compositeExpected) throws AtlasBaseException {
+        AtlasTypeDefGraphStoreV1 typeDefStore = makeTypeStore(registry);
+        AtlasStructType          structType   = (AtlasStructType) registry.getType(structDef.getName());
+        AtlasAttribute           attribute    = structType.getAttribute(attributeDef.getName());
+        String                   attribJson   = AtlasStructDefStoreV1.toJsonFromAttribute(attribute);
+        Map                      attrInfo     = AtlasType.fromJson(attribJson, Map.class);
+
+        Assert.assertEquals(attrInfo.get("isComposite"), compositeExpected);
+
+        return AtlasStructDefStoreV1.toAttributeDefFromJson(structDef, attrInfo, typeDefStore);
+    }
+
+    private void testV1toV2toV1Conversion(List<ClassTypeDefinition> typesToTest, boolean[] compositeExpected) throws AtlasBaseException {
+        List<AtlasEntityDef> convertedEntityDefs = convertV1toV2(typesToTest);
+        AtlasTypeRegistry    registry            = createRegistry(convertedEntityDefs);
+
+        for(int i = 0 ; i < convertedEntityDefs.size(); i++) {
+            AtlasEntityDef def =  convertedEntityDefs.get(i);
+
+            for (AtlasAttributeDef attrDef : def.getAttributeDefs()) {
+                AtlasAttributeDef converted = convertToJsonAndBack(registry, def, attrDef, compositeExpected[i]);
+
+                Assert.assertEquals(converted, attrDef);
+            }
+        }
+
+        List<ClassTypeDefinition> convertedBackTypeDefs = convertV2toV1(convertedEntityDefs);
+
+        for (int i = 0; i < typesToTest.size(); i++) {
+            ClassTypeDefinition convertedBack = convertedBackTypeDefs.get(i);
+
+            Assert.assertEquals(convertedBack, typesToTest.get(i));
+
+            List<AttributeDefinition> attributeDefinitions = convertedBack.getAttributeDefinitions();
+
+            if (attributeDefinitions.size() > 0) {
+                Assert.assertEquals(attributeDefinitions.get(0).getIsComposite(), compositeExpected[i]);
+            }
+        }
+    }
+
+    private List<ClassTypeDefinition> convertV2toV1(List<AtlasEntityDef> toConvert) throws AtlasBaseException {
+        AtlasTypeRegistry         reg    = createRegistry(toConvert);
+        List<ClassTypeDefinition> result = new ArrayList<>(toConvert.size());
+
+        for (int i = 0; i < toConvert.size(); i++) {
+            AtlasEntityDef      entityDef = toConvert.get(i);
+            AtlasEntityType     entity    = reg.getEntityTypeByName(entityDef.getName());
+            ClassTypeDefinition converted = TypeConverterUtil.toTypesDef(entity, reg).getClassTypes().get(0);
+
+            result.add(converted);
+        }
+
+        return result;
+    }
+
+    private AtlasTypeRegistry createRegistry(List<AtlasEntityDef> toConvert) throws AtlasBaseException {
+        AtlasTypeRegistry          reg = new AtlasTypeRegistry();
+        AtlasTransientTypeRegistry tmp = reg.lockTypeRegistryForUpdate();
+
+        tmp.addTypes(toConvert);
+        reg.releaseTypeRegistryForUpdate(tmp, true);
+
+        return reg;
+    }
+
+    private List<AtlasEntityDef> convertV1toV2(List<ClassTypeDefinition> types) throws AtlasBaseException {
+        List<ClassTypeDefinition> classTypeList       = new ArrayList(types);
+        TypesDef                  toConvert           = new TypesDef(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), classTypeList);
+        String                    json                = AtlasType.toV1Json(toConvert);
+        AtlasTypeRegistry         emptyRegistry       = new AtlasTypeRegistry();
+        AtlasTypesDef             converted           = TypeConverterUtil.toAtlasTypesDef(json, emptyRegistry);
+        List<AtlasEntityDef>      convertedEntityDefs = converted.getEntityDefs();
+
+        return convertedEntityDefs;
+    }
+}


[4/5] atlas git commit: ATLAS-2251: restored bunch of deleted tests

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/ZipSourceTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ZipSourceTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ZipSourceTest.java
new file mode 100644
index 0000000..1c1c68f
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ZipSourceTest.java
@@ -0,0 +1,189 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.impexp;
+
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.typedef.AtlasTypesDef;
+import org.testng.Assert;
+import org.testng.ITestContext;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.List;
+
+import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.getZipSource;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.AssertJUnit.assertTrue;
+
+public class ZipSourceTest {
+    @DataProvider(name = "zipFileStocks")
+    public static Object[][] getDataFromZipFile() throws IOException {
+        FileInputStream fs = ZipFileResourceTestUtils.getFileInputStream("stocks.zip");
+
+        return new Object[][] {{ new ZipSource(fs) }};
+    }
+
+    @DataProvider(name = "zipFileStocksFloat")
+    public static Object[][] getDataFromZipFileWithLongFloats() throws IOException {
+        FileInputStream fs = ZipFileResourceTestUtils.getFileInputStream("stocks-float.zip");
+
+        return new Object[][] {{ new ZipSource(fs) }};
+    }
+
+    @DataProvider(name = "sales")
+    public static Object[][] getDataFromQuickStart_v1_Sales(ITestContext context) throws IOException {
+        return getZipSource("sales-v1-full.zip");
+    }
+
+    @Test
+    public void improperInit_ReturnsNullCreationOrder() throws IOException, AtlasBaseException {
+        byte bytes[] = new byte[10];
+        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+        ZipSource zs = new ZipSource(bais);
+        List<String> s = zs.getCreationOrder();
+        Assert.assertNull(s);
+    }
+
+    @Test(dataProvider = "zipFileStocks")
+    public void examineContents_BehavesAsExpected(ZipSource zipSource) throws IOException, AtlasBaseException {
+        List<String> creationOrder = zipSource.getCreationOrder();
+
+        assertNotNull(creationOrder);
+        assertEquals(creationOrder.size(), 4);
+
+        AtlasTypesDef typesDef = zipSource.getTypesDef();
+        assertNotNull(typesDef);
+        assertEquals(typesDef.getEntityDefs().size(), 6);
+
+        useCreationOrderToFetchEntitiesWithExtInfo(zipSource, creationOrder);
+        useCreationOrderToFetchEntities(zipSource, creationOrder);
+        attemptToFetchNonExistentGuid_ReturnsNull(zipSource, "non-existent-guid");
+        verifyGuidRemovalOnImportComplete(zipSource, creationOrder.get(0));
+    }
+
+    private void useCreationOrderToFetchEntities(ZipSource zipSource, List<String> creationOrder) {
+        for (String guid : creationOrder) {
+            AtlasEntity e = zipSource.getByGuid(guid);
+            assertNotNull(e);
+        }
+    }
+
+    private void verifyGuidRemovalOnImportComplete(ZipSource zipSource, String guid) {
+        AtlasEntity e = zipSource.getByGuid(guid);
+        assertNotNull(e);
+
+        zipSource.onImportComplete(guid);
+
+        e = zipSource.getByGuid(guid);
+        Assert.assertNull(e);
+    }
+
+    private void attemptToFetchNonExistentGuid_ReturnsNull(ZipSource zipSource, String guid) {
+        AtlasEntity e = zipSource.getByGuid(guid);
+        Assert.assertNull(e);
+    }
+
+    private void useCreationOrderToFetchEntitiesWithExtInfo(ZipSource zipSource, List<String> creationOrder) throws AtlasBaseException {
+        for (String guid : creationOrder) {
+            AtlasEntity.AtlasEntityExtInfo e = zipSource.getEntityWithExtInfo(guid);
+            assertNotNull(e);
+        }
+    }
+
+    @Test(dataProvider = "zipFileStocks")
+    public void iteratorBehavor_WorksAsExpected(ZipSource zipSource) throws IOException, AtlasBaseException {
+        Assert.assertTrue(zipSource.hasNext());
+
+        List<String> creationOrder = zipSource.getCreationOrder();
+        for (int i = 0; i < creationOrder.size(); i++) {
+            AtlasEntity e = zipSource.next();
+
+            assertNotNull(e);
+            assertEquals(e.getGuid(), creationOrder.get(i));
+        }
+
+        assertFalse(zipSource.hasNext());
+    }
+
+    @Test(dataProvider = "sales")
+    public void iteratorSetPositionBehavor(ZipSource zipSource) throws IOException, AtlasBaseException {
+        Assert.assertTrue(zipSource.hasNext());
+
+        List<String> creationOrder = zipSource.getCreationOrder();
+        int moveToPosition_2 = 2;
+        zipSource.setPosition(moveToPosition_2);
+
+        assertEquals(zipSource.getPosition(), moveToPosition_2);
+        assertTrue(zipSource.getPosition() < creationOrder.size());
+
+        assertTrue(zipSource.hasNext());
+        for (int i = 1; i < 4; i++) {
+            zipSource.next();
+            assertEquals(zipSource.getPosition(), moveToPosition_2 + i);
+        }
+
+        assertTrue(zipSource.hasNext());
+    }
+
+    @Test(dataProvider = "zipFileStocksFloat")
+    public void attemptToSerializeLongFloats(ZipSource zipSource) throws IOException, AtlasBaseException {
+        Assert.assertTrue(zipSource.hasNext());
+        assertTrue(zipSource.hasNext());
+        assertTrue(zipSource.hasNext());
+
+        AtlasEntity.AtlasEntityWithExtInfo e = zipSource.getNextEntityWithExtInfo();
+        assertNotNull(e);
+        assertTrue(e.getEntity().getClassifications().size() > 0);
+        assertNotNull(e.getEntity().getClassifications().get(0).getAttribute("fv"));
+        assertEquals(e.getEntity().getClassifications().get(0).getAttribute("fv").toString(), "3.4028235E+38");
+
+        assertTrue(zipSource.hasNext());
+    }
+
+    @Test(dataProvider = "zipFileStocks")
+    public void applyTransformation(ZipSource zipSource) throws IOException, AtlasBaseException {
+        ImportTransforms transforms = getTransformForHiveDB();
+        zipSource.setImportTransform(transforms);
+
+        Assert.assertTrue(zipSource.hasNext());
+        List<String> creationOrder = zipSource.getCreationOrder();
+        for (int i = 0; i < creationOrder.size(); i++) {
+            AtlasEntity e = zipSource.next();
+            if(e.getTypeName().equals("hive_db")) {
+                Object o = e.getAttribute("qualifiedName");
+                String s = (String) o;
+
+                assertNotNull(e);
+                assertTrue(s.contains("@cl2"));
+                break;
+            }
+        }
+    }
+
+    private ImportTransforms getTransformForHiveDB() {
+        ImportTransforms tr = ImportTransforms.fromJson("{ \"hive_db\": { \"qualifiedName\": [ \"replace:@cl1:@cl2\" ] } }");
+
+        return tr;
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java
new file mode 100644
index 0000000..9088470
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java
@@ -0,0 +1,644 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.store.graph;
+
+import com.google.inject.Inject;
+import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.TestUtilsV2;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.SearchFilter;
+import org.apache.atlas.model.typedef.*;
+import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
+import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Arrays;
+import java.util.Date;
+
+import static org.testng.Assert.*;
+
+@Guice(modules = TestModules.TestOnlyModule.class)
+public class AtlasTypeDefGraphStoreTest {
+    private static final Logger LOG = LoggerFactory.getLogger(AtlasTypeDefGraphStoreTest.class);
+
+    @Inject
+    private
+    AtlasTypeDefStore typeDefStore;
+
+    @BeforeTest
+    public void setupTest() {
+        RequestContextV1.clear();
+        RequestContextV1.get().setUser(TestUtilsV2.TEST_USER);
+    }
+
+    @Test
+    public void testGet() {
+        try {
+            AtlasTypesDef typesDef = typeDefStore.searchTypesDef(new SearchFilter());
+            assertNotNull(typesDef.getEnumDefs());
+            assertEquals(typesDef.getStructDefs().size(), 0);
+            assertNotNull(typesDef.getStructDefs());
+            assertEquals(typesDef.getClassificationDefs().size(), 0);
+            assertNotNull(typesDef.getClassificationDefs());
+            assertEquals(typesDef.getEntityDefs().size(), 0);
+            assertNotNull(typesDef.getEntityDefs());
+        } catch (AtlasBaseException e) {
+            fail("Search of types shouldn't have failed");
+        }
+    }
+
+    @Test(dataProvider = "invalidGetProvider", dependsOnMethods = "testGet")
+    public void testInvalidGet(String name, String guid){
+        try {
+            assertNull(typeDefStore.getEnumDefByName(name));
+            fail("Exception expected for invalid name");
+        } catch (AtlasBaseException e) {
+        }
+
+        try {
+            assertNull(typeDefStore.getEnumDefByGuid(guid));
+            fail("Exception expected for invalid guid");
+        } catch (AtlasBaseException e) {
+        }
+
+        try {
+            assertNull(typeDefStore.getStructDefByName(name));
+            fail("Exception expected for invalid name");
+        } catch (AtlasBaseException e) {
+        }
+
+        try {
+            assertNull(typeDefStore.getStructDefByGuid(guid));
+            fail("Exception expected for invalid guid");
+        } catch (AtlasBaseException e) {
+        }
+
+        try {
+            assertNull(typeDefStore.getClassificationDefByName(name));
+            fail("Exception expected for invalid name");
+        } catch (AtlasBaseException e) {
+        }
+
+        try {
+            assertNull(typeDefStore.getClassificationDefByGuid(guid));
+            fail("Exception expected for invalid guid");
+        } catch (AtlasBaseException e) {
+        }
+
+        try {
+            assertNull(typeDefStore.getEntityDefByName(name));
+            fail("Exception expected for invalid name");
+        } catch (AtlasBaseException e) {
+        }
+
+        try {
+            assertNull(typeDefStore.getEntityDefByGuid(guid));
+            fail("Exception expected for invalid guid");
+        } catch (AtlasBaseException e) {
+        }
+    }
+
+    @DataProvider
+    public Object[][] invalidGetProvider(){
+        return new Object[][] {
+                {"name1", "guid1"},
+                {"", ""},
+                {null, null}
+        };
+    }
+
+    @DataProvider
+    public Object[][] validCreateDeptTypes(){
+        return new Object[][] {
+                {TestUtilsV2.defineDeptEmployeeTypes()}
+        };
+    }
+
+    @DataProvider
+    public Object[][] validUpdateDeptTypes(){
+        AtlasTypesDef typesDef = TestUtilsV2.defineValidUpdatedDeptEmployeeTypes();
+        return new Object[][] {
+                {typesDef}
+        };
+    }
+
+    @DataProvider
+    public Object[][] allCreatedTypes(){
+        // Capture all the types that are getting created or updated here.
+        AtlasTypesDef updatedTypeDefs = TestUtilsV2.defineValidUpdatedDeptEmployeeTypes();
+        AtlasTypesDef allTypeDefs = new AtlasTypesDef();
+        allTypeDefs.getEnumDefs().addAll(updatedTypeDefs.getEnumDefs());
+        allTypeDefs.getStructDefs().addAll(updatedTypeDefs.getStructDefs());
+        allTypeDefs.getClassificationDefs().addAll(updatedTypeDefs.getClassificationDefs());
+        allTypeDefs.getEntityDefs().addAll(updatedTypeDefs.getEntityDefs());
+        allTypeDefs.getEntityDefs().addAll(TestUtilsV2.getEntityWithValidSuperType());
+        return new Object[][] {{allTypeDefs}};
+    }
+
+    @DataProvider
+    public Object[][] invalidCreateTypes(){
+        // TODO: Create invalid type in TestUtilsV2
+        return new Object[][] {
+        };
+    }
+
+    @DataProvider
+    public Object[][] invalidUpdateTypes(){
+        return new Object[][] {
+                {TestUtilsV2.defineInvalidUpdatedDeptEmployeeTypes()}
+        };
+    }
+
+    @Test(dependsOnMethods = {"testGet"}, dataProvider = "validCreateDeptTypes")
+    public void testCreateDept(AtlasTypesDef atlasTypesDef) {
+        AtlasTypesDef existingTypesDef = null;
+        try {
+            existingTypesDef = typeDefStore.searchTypesDef(new SearchFilter());
+        } catch (AtlasBaseException e) {
+            // ignore
+        }
+
+        assertNotEquals(atlasTypesDef, existingTypesDef, "Types to be created already exist in the system");
+        AtlasTypesDef createdTypesDef = null;
+        try {
+            createdTypesDef = typeDefStore.createTypesDef(atlasTypesDef);
+            assertNotNull(createdTypesDef);
+            assertTrue(createdTypesDef.getEnumDefs().containsAll(atlasTypesDef.getEnumDefs()), "EnumDefs create failed");
+            assertTrue(createdTypesDef.getClassificationDefs().containsAll(atlasTypesDef.getClassificationDefs()), "ClassificationDef create failed");
+            assertTrue(createdTypesDef.getStructDefs().containsAll(atlasTypesDef.getStructDefs()), "StructDef creation failed");
+            Assert.assertEquals(createdTypesDef.getEntityDefs(), atlasTypesDef.getEntityDefs());
+
+        } catch (AtlasBaseException e) {
+            fail("Creation of Types should've been a success", e);
+        }
+    }
+
+    @Test(dependsOnMethods = {"testCreateDept"}, dataProvider = "validUpdateDeptTypes")
+    public void testUpdate(AtlasTypesDef atlasTypesDef){
+        try {
+            AtlasTypesDef updatedTypesDef = typeDefStore.updateTypesDef(atlasTypesDef);
+            assertNotNull(updatedTypesDef);
+
+            assertEquals(updatedTypesDef.getEnumDefs().size(), atlasTypesDef.getEnumDefs().size(), "EnumDefs update failed");
+            assertEquals(updatedTypesDef.getClassificationDefs().size(), atlasTypesDef.getClassificationDefs().size(), "ClassificationDef update failed");
+            assertEquals(updatedTypesDef.getStructDefs().size(), atlasTypesDef.getStructDefs().size(), "StructDef update failed");
+            assertEquals(updatedTypesDef.getEntityDefs().size(), atlasTypesDef.getEntityDefs().size(), "EntityDef update failed");
+
+            // Try another update round by name and GUID
+            for (AtlasEnumDef enumDef : updatedTypesDef.getEnumDefs()) {
+                AtlasEnumDef updated = typeDefStore.updateEnumDefByGuid(enumDef.getGuid(), enumDef);
+                assertNotNull(updated);
+            }
+            for (AtlasEnumDef enumDef : atlasTypesDef.getEnumDefs()) {
+                AtlasEnumDef updated = typeDefStore.updateEnumDefByName(enumDef.getName(), enumDef);
+                assertNotNull(updated);
+            }
+
+            // Try another update round by name and GUID
+            for (AtlasClassificationDef classificationDef : updatedTypesDef.getClassificationDefs()) {
+                AtlasClassificationDef updated = typeDefStore.updateClassificationDefByGuid(classificationDef.getGuid(), classificationDef);
+                assertNotNull(updated);
+            }
+            for (AtlasClassificationDef classificationDef : atlasTypesDef.getClassificationDefs()) {
+                AtlasClassificationDef updated = typeDefStore.updateClassificationDefByName(classificationDef.getName(), classificationDef);
+                assertNotNull(updated);
+            }
+
+            // Try another update round by name and GUID
+            for (AtlasStructDef structDef : updatedTypesDef.getStructDefs()) {
+                AtlasStructDef updated = typeDefStore.updateStructDefByGuid(structDef.getGuid(), structDef);
+                assertNotNull(updated);
+            }
+            for (AtlasStructDef structDef : atlasTypesDef.getStructDefs()) {
+                AtlasStructDef updated = typeDefStore.updateStructDefByName(structDef.getName(), structDef);
+                assertNotNull(updated);
+            }
+
+            // Try another update round by name and GUID
+            for (AtlasEntityDef entityDef : updatedTypesDef.getEntityDefs()) {
+                AtlasEntityDef updated = typeDefStore.updateEntityDefByGuid(entityDef.getGuid(), entityDef);
+                assertNotNull(updated);
+            }
+            for (AtlasEntityDef entityDef : atlasTypesDef.getEntityDefs()) {
+                AtlasEntityDef updated = typeDefStore.updateEntityDefByName(entityDef.getName(), entityDef);
+                assertNotNull(updated);
+            }
+
+        } catch (AtlasBaseException e) {
+            fail("TypeDef updates should've succeeded");
+        }
+    }
+
+    @Test(enabled = false, dependsOnMethods = {"testCreateDept"})
+    public void testUpdateWithMandatoryFields(){
+        AtlasTypesDef atlasTypesDef = TestUtilsV2.defineInvalidUpdatedDeptEmployeeTypes();
+        List<AtlasEnumDef> enumDefsToUpdate = atlasTypesDef.getEnumDefs();
+        List<AtlasClassificationDef> classificationDefsToUpdate = atlasTypesDef.getClassificationDefs();
+        List<AtlasStructDef> structDefsToUpdate = atlasTypesDef.getStructDefs();
+        List<AtlasEntityDef> entityDefsToUpdate = atlasTypesDef.getEntityDefs();
+
+        AtlasTypesDef onlyEnums = new AtlasTypesDef(enumDefsToUpdate,
+                Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST);
+
+        AtlasTypesDef onlyStructs = new AtlasTypesDef(Collections.EMPTY_LIST,
+                structDefsToUpdate, Collections.EMPTY_LIST, Collections.EMPTY_LIST);
+
+        AtlasTypesDef onlyClassification = new AtlasTypesDef(Collections.EMPTY_LIST,
+                Collections.EMPTY_LIST, classificationDefsToUpdate, Collections.EMPTY_LIST);
+
+        AtlasTypesDef onlyEntities = new AtlasTypesDef(Collections.EMPTY_LIST,
+                Collections.EMPTY_LIST, Collections.EMPTY_LIST, entityDefsToUpdate);
+
+        try {
+            AtlasTypesDef updated = typeDefStore.updateTypesDef(onlyEnums);
+            assertNotNull(updated);
+        } catch (AtlasBaseException ignored) {}
+
+        try {
+            AtlasTypesDef updated = typeDefStore.updateTypesDef(onlyClassification);
+            assertNotNull(updated);
+            assertEquals(updated.getClassificationDefs().size(), 0, "Updates should've failed");
+        } catch (AtlasBaseException ignored) {}
+
+        try {
+            AtlasTypesDef updated = typeDefStore.updateTypesDef(onlyStructs);
+            assertNotNull(updated);
+            assertEquals(updated.getStructDefs().size(), 0, "Updates should've failed");
+        } catch (AtlasBaseException ignored) {}
+
+        try {
+            AtlasTypesDef updated = typeDefStore.updateTypesDef(onlyEntities);
+            assertNotNull(updated);
+            assertEquals(updated.getEntityDefs().size(), 0, "Updates should've failed");
+        } catch (AtlasBaseException ignored) {}
+    }
+
+    // This should run after all the update calls
+    @Test(dependsOnMethods = {"testUpdate"}, dataProvider = "allCreatedTypes")
+    public void testDelete(AtlasTypesDef atlasTypesDef){
+        try {
+            typeDefStore.deleteTypesDef(atlasTypesDef);
+        } catch (AtlasBaseException e) {
+            fail("Deletion should've succeeded");
+        }
+    }
+
+    @Test(dependsOnMethods = "testGet")
+    public void testCreateWithValidAttributes(){
+        AtlasTypesDef hiveTypes = TestUtilsV2.defineHiveTypes();
+        try {
+            AtlasTypesDef createdTypes = typeDefStore.createTypesDef(hiveTypes);
+            assertEquals(hiveTypes.getEnumDefs(), createdTypes.getEnumDefs(), "Data integrity issue while persisting");
+            assertEquals(hiveTypes.getStructDefs(), createdTypes.getStructDefs(), "Data integrity issue while persisting");
+            assertEquals(hiveTypes.getClassificationDefs(), createdTypes.getClassificationDefs(), "Data integrity issue while persisting");
+            assertEquals(hiveTypes.getEntityDefs(), createdTypes.getEntityDefs(), "Data integrity issue while persisting");
+        } catch (AtlasBaseException e) {
+            fail("Hive Type creation should've succeeded");
+        }
+    }
+
+    @Test(enabled = false)
+    public void testCreateWithInvalidAttributes(){
+    }
+
+    @Test(dependsOnMethods = "testGet")
+    public void testCreateWithValidSuperTypes(){
+        // Test Classification with supertype
+        List<AtlasClassificationDef> classificationDefs = TestUtilsV2.getClassificationWithValidSuperType();
+
+        AtlasTypesDef toCreate = new AtlasTypesDef(Collections.<AtlasEnumDef>emptyList(),
+                Collections.<AtlasStructDef>emptyList(),
+                classificationDefs,
+                Collections.<AtlasEntityDef>emptyList());
+        try {
+            AtlasTypesDef created = typeDefStore.createTypesDef(toCreate);
+            assertEquals(created.getClassificationDefs(), toCreate.getClassificationDefs(),
+                    "Classification creation with valid supertype should've succeeded");
+        } catch (AtlasBaseException e) {
+            fail("Classification creation with valid supertype should've succeeded");
+        }
+
+        // Test Entity with supertype
+        List<AtlasEntityDef> entityDefs = TestUtilsV2.getEntityWithValidSuperType();
+        toCreate = new AtlasTypesDef(Collections.<AtlasEnumDef>emptyList(),
+                Collections.<AtlasStructDef>emptyList(),
+                Collections.<AtlasClassificationDef>emptyList(),
+                entityDefs);
+        try {
+            AtlasTypesDef created = typeDefStore.createTypesDef(toCreate);
+            assertEquals(created.getEntityDefs(), toCreate.getEntityDefs(),
+                    "Entity creation with valid supertype should've succeeded");
+        } catch (AtlasBaseException e) {
+            fail("Entity creation with valid supertype should've succeeded");
+        }
+    }
+
+    @Test(dependsOnMethods = "testGet")
+    public void testCreateWithInvalidSuperTypes(){
+        AtlasTypesDef typesDef;
+
+        // Test Classification with supertype
+        AtlasClassificationDef classificationDef = TestUtilsV2.getClassificationWithInvalidSuperType();
+        typesDef = new AtlasTypesDef();
+        typesDef.getClassificationDefs().add(classificationDef);
+        try {
+            AtlasTypesDef created = typeDefStore.createTypesDef(typesDef);
+            fail("Classification creation with invalid supertype should've failed");
+        } catch (AtlasBaseException e) {
+            typesDef = null;
+        }
+
+        // Test Entity with supertype
+        AtlasEntityDef entityDef = TestUtilsV2.getEntityWithInvalidSuperType();
+        typesDef = new AtlasTypesDef();
+        typesDef.getEntityDefs().add(entityDef);
+        try {
+            AtlasTypesDef created = typeDefStore.createTypesDef(typesDef);
+            fail("Entity creation with invalid supertype should've failed");
+        } catch (AtlasBaseException e) {}
+
+    }
+
+    @Test(dependsOnMethods = "testGet")
+    public void testCreateClassificationDefWithValidEntityType(){
+        final String entityTypeName ="testCreateClassificationDefWithValidEntityTypeEntity1";
+        final String classificationTypeName ="testCreateClassificationDefWithValidEntityTypeClassification1";
+
+        List<AtlasEntityDef> entityDefs = TestUtilsV2.getEntityWithName(entityTypeName);
+
+        // Test Classification with entitytype
+        List<AtlasClassificationDef> classificationDefs = TestUtilsV2.getClassificationWithName(classificationTypeName);
+
+        Set<String> entityTypeNames =  new HashSet<String>();
+        entityTypeNames.add(entityTypeName);
+        classificationDefs.get(0).setEntityTypes(entityTypeNames);
+        AtlasTypesDef toCreate = new AtlasTypesDef(Collections.<AtlasEnumDef>emptyList(),
+                Collections.<AtlasStructDef>emptyList(),
+                classificationDefs,
+                entityDefs);
+        try {
+            AtlasTypesDef created = typeDefStore.createTypesDef(toCreate);
+            assertEquals(created.getClassificationDefs(), toCreate.getClassificationDefs(),
+                    "Classification creation with valid entitytype should've succeeded");
+        } catch (AtlasBaseException e) {
+            fail("Classification creation with valid entitytype should've succeeded. Failed with " + e.getMessage());
+        }
+    }
+
+    @Test(dependsOnMethods = "testGet")
+    public void testCreateWithInvalidEntityType(){
+        final String classificationTypeName ="testCreateClassificationDefWithInvalidEntityTypeClassification1";
+        // Test Classification with entitytype
+        List<AtlasClassificationDef> classificationDefs = TestUtilsV2.getClassificationWithName(classificationTypeName);
+
+        Set<String> entityTypeNames =  new HashSet<String>();
+        entityTypeNames.add("cccc");
+        classificationDefs.get(0).setEntityTypes(entityTypeNames);
+        AtlasTypesDef toCreate = new AtlasTypesDef(Collections.<AtlasEnumDef>emptyList(),
+                Collections.<AtlasStructDef>emptyList(),
+                classificationDefs,
+                Collections.<AtlasEntityDef>emptyList());
+        try {
+            AtlasTypesDef created = typeDefStore.createTypesDef(toCreate);
+            fail("Classification creation with invalid entitytype should've failed");
+        } catch (AtlasBaseException e) {
+
+        }
+    }
+
+    /**
+     * test that specifying an entitytype in a child classificationDef when then parent has unrestricted entityTypes fails.
+     */
+    @Test(dependsOnMethods = "testGet")
+    public void testCreateWithInvalidEntityType2(){
+        final String classificationTypeName1 ="testCreateClassificationDefWithInvalidEntityType2Classification1";
+        final String classificationTypeName2 ="testCreateClassificationDefWithInvalidEntityType2Classification2";
+        final String entityTypeName1 ="testCreateClassificationDefWithInvalidEntityType2Entity1";
+
+        // Test Classification with entitytype
+        AtlasClassificationDef classificationDef1 = TestUtilsV2.getSingleClassificationWithName(classificationTypeName1);
+        AtlasClassificationDef classificationDef2 = TestUtilsV2.getSingleClassificationWithName(classificationTypeName2);
+        List<AtlasEntityDef> entityDefs = TestUtilsV2.getEntityWithName(entityTypeName1);
+
+
+        Set<String> entityTypeNames =  new HashSet<String>();
+        entityTypeNames.add(entityTypeName1);
+
+        Set<String> superTypes =  new HashSet<String>();
+        superTypes.add(classificationTypeName1);
+
+        classificationDef2.setSuperTypes(superTypes);
+        classificationDef1.setEntityTypes(entityTypeNames);
+
+        TestUtilsV2.populateSystemAttributes(classificationDef1);
+        TestUtilsV2.populateSystemAttributes(classificationDef2);
+
+        List<AtlasClassificationDef>  classificationDefs = Arrays.asList(classificationDef1,classificationDef2);
+
+        AtlasTypesDef toCreate = new AtlasTypesDef(Collections.<AtlasEnumDef>emptyList(),
+                Collections.<AtlasStructDef>emptyList(),
+                classificationDefs,
+                Collections.<AtlasEntityDef>emptyList());
+        try {
+            AtlasTypesDef created = typeDefStore.createTypesDef(toCreate);
+            fail("Classification creation with invalid entitytype should've failed");
+        } catch (AtlasBaseException e) {
+
+        }
+    }
+
+    /**
+     * test that specifying an entitytype in a child classificationDef which is not in the parent fails
+     */
+    @Test(dependsOnMethods = "testGet")
+    public void testCreateWithInvalidEntityType3(){
+        final String classificationTypeName1 ="testCreateClassificationDefWithInvalidEntityType3Classification1";
+        final String classificationTypeName2 ="testCreateClassificationDefWithInvalidEntityType3Classification2";
+        final String entityTypeName1 ="testCreateClassificationDefWithInvalidEntityType3Entity1";
+        final String entityTypeName2 ="testCreateClassificationDefWithInvalidEntityType3Entity2";
+
+
+        // Test Classification with entitytype
+        AtlasClassificationDef classificationDef1 = TestUtilsV2.getSingleClassificationWithName(classificationTypeName1);
+        AtlasClassificationDef classificationDef2 = TestUtilsV2.getSingleClassificationWithName(classificationTypeName2);
+        AtlasEntityDef entityDef1 = TestUtilsV2.getSingleEntityWithName(entityTypeName1);
+        AtlasEntityDef entityDef2 = TestUtilsV2.getSingleEntityWithName(entityTypeName2);
+
+        Set<String> entityTypeNames1 =  new HashSet<String>();
+        entityTypeNames1.add(entityTypeName1);
+
+        Set<String> entityTypeNames2 =  new HashSet<String>();
+        entityTypeNames2.add(entityTypeName2);
+
+        Set<String> superTypes =  new HashSet<String>();
+        superTypes.add(classificationTypeName1);
+
+        classificationDef1.setEntityTypes(entityTypeNames1);
+
+
+        classificationDef2.setSuperTypes(superTypes);
+        classificationDef2.setEntityTypes(entityTypeNames2);
+
+        TestUtilsV2.populateSystemAttributes(classificationDef1);
+        TestUtilsV2.populateSystemAttributes(classificationDef2);
+        TestUtilsV2.populateSystemAttributes(entityDef1);
+        TestUtilsV2.populateSystemAttributes(entityDef2);
+
+        List<AtlasClassificationDef>  classificationDefs = Arrays.asList(classificationDef1,classificationDef2);
+        List<AtlasEntityDef>  entityDefs = Arrays.asList(entityDef1,entityDef2);
+
+        AtlasTypesDef toCreate = new AtlasTypesDef(Collections.<AtlasEnumDef>emptyList(),
+                Collections.<AtlasStructDef>emptyList(),
+                classificationDefs,
+                entityDefs);
+        try {
+            AtlasTypesDef created = typeDefStore.createTypesDef(toCreate);
+            fail("Classification creation with invalid entitytype should've failed");
+        } catch (AtlasBaseException e) {
+
+        }
+    }
+
+    @Test(dependsOnMethods = "testGet")
+    public void testSearchFunctionality() {
+        SearchFilter searchFilter = new SearchFilter();
+        searchFilter.setParam(SearchFilter.PARAM_SUPERTYPE, "Person");
+
+        try {
+            AtlasTypesDef typesDef = typeDefStore.searchTypesDef(searchFilter);
+            assertNotNull(typesDef);
+            assertNotNull(typesDef.getEntityDefs());
+            assertEquals(typesDef.getEntityDefs().size(), 3);
+        } catch (AtlasBaseException e) {
+            fail("Search should've succeeded", e);
+        }
+    }
+
+    @Test(dependsOnMethods = "testGet")
+    public void testTypeDeletionAndRecreate() {
+        AtlasClassificationDef aTag = new AtlasClassificationDef("testTag");
+        AtlasAttributeDef attributeDef = new AtlasAttributeDef("testAttribute", "string", true,
+                AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+                false, true,
+                Collections.<AtlasStructDef.AtlasConstraintDef>emptyList());
+        aTag.addAttribute(attributeDef);
+
+        AtlasTypesDef typesDef = new AtlasTypesDef();
+        typesDef.setClassificationDefs(Arrays.asList(aTag));
+
+        try {
+            typeDefStore.createTypesDef(typesDef);
+        } catch (AtlasBaseException e) {
+            fail("Tag creation should've succeeded");
+        }
+
+        try {
+            typeDefStore.deleteTypesDef(typesDef);
+        } catch (AtlasBaseException e) {
+            fail("Tag deletion should've succeeded");
+        }
+
+        aTag = new AtlasClassificationDef("testTag");
+        attributeDef = new AtlasAttributeDef("testAttribute", "int", true,
+                AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+                false, true,
+                Collections.<AtlasStructDef.AtlasConstraintDef>emptyList());
+        aTag.addAttribute(attributeDef);
+        typesDef.setClassificationDefs(Arrays.asList(aTag));
+
+        try {
+            typeDefStore.createTypesDef(typesDef);
+        } catch (AtlasBaseException e) {
+            fail("Tag re-creation should've succeeded");
+        }
+    }
+
+    @Test(dependsOnMethods = "testGet")
+    public void testTypeRegistryIsUpdatedAfterGraphStorage() throws AtlasBaseException {
+      String classificationDef = "{"
+          + "\"name\":\"test_classification_11\","
+          + "\"description\":\"\","
+          + "\"createdBy\":\"admin\","
+          + "\"superTypes\":[],"
+          + "\"attributeDefs\":[{"
+          + "\"name\":\"test_class_11\","
+          + "\"typeName\":\"string\","
+          + "\"isOptional\":true,"
+          + "\"isUnique\":true,"
+          + "\"isIndexable\":true,"
+          + "\"cardinality\":\"SINGLE\","
+          + "\"valuesMinCount\":0,"
+          + "\"valuesMaxCount\":1}]}";
+
+      String jsonStr = "{"
+          + "\"classificationDefs\":[" + classificationDef + "],"
+          + "\"entityDefs\":[],"
+          + "\"enumDefs\":[],"
+          + "\"structDefs\":[]}";
+
+      // create type from json string
+      AtlasTypesDef testTypesDefFromJson = AtlasType.fromJson(jsonStr, AtlasTypesDef.class);
+      AtlasTypesDef createdTypesDef = typeDefStore.createTypesDef(testTypesDefFromJson);
+      // check returned type
+      assertEquals("test_classification_11", createdTypesDef.getClassificationDefs().get(0).getName());
+      assertTrue(createdTypesDef.getClassificationDefs().get(0).getAttributeDefs().get(0).getIsIndexable());
+      // save guid
+      String guid = createdTypesDef.getClassificationDefs().get(0).getGuid();
+      Date createdTime = createdTypesDef.getClassificationDefs().get(0).getCreateTime();
+
+      // get created type and check again
+      AtlasClassificationDef getBackFromCache = typeDefStore.getClassificationDefByName("test_classification_11");
+      assertEquals("test_classification_11", getBackFromCache.getName());
+      assertTrue(getBackFromCache.getAttributeDefs().get(0).getIsIndexable());
+      assertEquals(guid, getBackFromCache.getGuid());
+      assertNotNull(getBackFromCache.getCreatedBy());
+      assertEquals(createdTime, getBackFromCache.getCreateTime());
+
+      // update type, change isIndexable, check the update result
+      testTypesDefFromJson = AtlasType.fromJson(jsonStr, AtlasTypesDef.class);
+      testTypesDefFromJson.getClassificationDefs().get(0).getAttributeDefs().get(0).setIsIndexable(false);
+      AtlasTypesDef updatedTypesDef = typeDefStore.updateTypesDef(testTypesDefFromJson);
+      assertEquals("test_classification_11", updatedTypesDef.getClassificationDefs().get(0).getName());
+      assertFalse(updatedTypesDef.getClassificationDefs().get(0).getAttributeDefs().get(0).getIsIndexable());
+      assertEquals(guid, updatedTypesDef.getClassificationDefs().get(0).getGuid());
+      assertEquals(createdTime, updatedTypesDef.getClassificationDefs().get(0).getCreateTime());
+
+      // get updated type (both by name and guid) and check again
+      getBackFromCache = typeDefStore.getClassificationDefByName("test_classification_11");
+      assertEquals("test_classification_11", getBackFromCache.getName());
+      assertFalse(getBackFromCache.getAttributeDefs().get(0).getIsIndexable());
+      assertEquals(guid, getBackFromCache.getGuid());
+      assertEquals(createdTime, getBackFromCache.getCreateTime());
+      getBackFromCache = typeDefStore.getClassificationDefByGuid(guid);
+      assertEquals("test_classification_11", getBackFromCache.getName());
+      assertFalse(getBackFromCache.getAttributeDefs().get(0).getIsIndexable());
+      assertEquals(guid, getBackFromCache.getGuid());
+      assertEquals(createdTime, getBackFromCache.getCreateTime());
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1Test.java
new file mode 100644
index 0000000..1198283
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1Test.java
@@ -0,0 +1,73 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.store.graph.v1;
+
+import com.google.inject.Inject;
+import org.apache.atlas.ApplicationProperties;
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.typedef.AtlasEntityDef;
+import org.apache.atlas.repository.graph.AtlasGraphProvider;
+import org.apache.atlas.type.AtlasTypeUtil;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import java.util.Collections;
+
+/**
+ * Tests for AtlasEntityStoreV1
+ */
+@Guice(modules = TestModules.TestOnlyModule.class)
+public class AtlasEntityDefStoreV1Test {
+
+    @Inject
+    private
+    AtlasEntityDefStoreV1 entityDefStore;
+
+    @DataProvider
+    public Object[][] invalidAttributeNameWithReservedKeywords(){
+        AtlasEntityDef invalidAttrNameType =
+            AtlasTypeUtil.createClassTypeDef("Invalid_Attribute_Type", "description", Collections.emptySet(),
+                AtlasTypeUtil.createRequiredAttrDef("order", "string"),
+                AtlasTypeUtil.createRequiredAttrDef("limit", "string"));
+
+        return new Object[][] {{
+            invalidAttrNameType
+        }};
+    }
+
+    @Test(dataProvider = "invalidAttributeNameWithReservedKeywords")
+    public void testCreateTypeWithReservedKeywords(AtlasEntityDef atlasEntityDef) throws AtlasException {
+        try {
+            ApplicationProperties.get().setProperty(AtlasAbstractDefStoreV1.ALLOW_RESERVED_KEYWORDS, false);
+            entityDefStore.create(atlasEntityDef, null);
+        } catch (AtlasBaseException e) {
+            Assert.assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.ATTRIBUTE_NAME_INVALID);
+        }
+    }
+
+    @AfterClass
+    public void clear(){
+        AtlasGraphProvider.cleanup();
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1BulkImportPercentTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1BulkImportPercentTest.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1BulkImportPercentTest.java
new file mode 100644
index 0000000..73dfe37
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1BulkImportPercentTest.java
@@ -0,0 +1,167 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.store.graph.v1;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.slf4j.Logger;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class AtlasEntityStoreV1BulkImportPercentTest {
+
+    private final int MAX_PERCENT = 100;
+    private List<Integer> percentHolder;
+    private Logger log;
+
+    public void setupPercentHolder(int max) {
+        percentHolder = new ArrayList<>();
+    }
+
+    @BeforeClass
+    void mockLog() {
+        log = mock(Logger.class);
+
+        doAnswer(new Answer() {
+            @Override
+            public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
+                Object[] args = invocationOnMock.getArguments();
+                Integer d = (Integer) args[1];
+                percentHolder.add(d.intValue());
+                return null;
+            }
+        }).when(log).info(anyString(), anyFloat(), anyInt(), anyString());
+    }
+
+    @Test
+    public void percentTest_Equal4() throws Exception {
+        runWithSize(4);
+        assertEqualsForPercentHolder(25.0, 50.0, 75.0, 100.0);
+    }
+
+    @Test
+    public void percentTest_Equal10() throws Exception {
+        runWithSize(10);
+
+        assertEqualsForPercentHolder(10.0, 20.0, 30.0, 40.0, 50, 60, 70, 80, 90, 100);
+    }
+
+    private void assertEqualsForPercentHolder(double... expected) {
+        assertEquals(percentHolder.size(), expected.length);
+        Object actual[] = percentHolder.toArray();
+        for (int i = 0; i < expected.length; i++) {
+            assertTrue((int) Double.compare((int) actual[i], expected[i]) == 0);
+        }
+    }
+
+    @Test
+    public void bulkImportPercentageTestLessThan100() throws Exception {
+        int streamSize = 20;
+
+        runWithSize(streamSize);
+        assertEqualsForPercentHolder(5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100);
+    }
+
+    @Test
+    public void percentTest_Equal101() throws Exception {
+        int streamSize = 101;
+
+        double[] expected = fillPercentHolderWith100();
+
+        runWithSize(streamSize);
+        assertEqualsForPercentHolder(expected);
+    }
+
+    @Test
+    public void percentTest_Equal200() throws Exception {
+        int streamSize = 200;
+
+        double[] expected = fillPercentHolderWith100();
+
+        runWithSize(streamSize);
+        assertEqualsForPercentHolder(expected);
+    }
+
+    @Test
+    public void percentTest_Equal202() throws Exception {
+        int streamSize = 202;
+
+        double[] expected = fillPercentHolderWith100();
+
+        runWithSize(streamSize);
+        assertEqualsForPercentHolder(expected);
+    }
+
+    @Test
+    public void percentTest_Equal1001() throws Exception {
+        int streamSize = 1001;
+        double[] expected = fillPercentHolderWith100();
+
+        runWithSize(streamSize);
+        assertEqualsForPercentHolder(expected);
+    }
+
+    @Test
+    public void percentTest_Equal4323() throws Exception {
+        int streamSize = 4323;
+
+        double[] expected = fillPercentHolderWith100();
+        runWithSize(streamSize);
+        assertEqualsForPercentHolder(expected);
+    }
+
+    @Test
+    public void percentTest_Equal269() throws Exception {
+        int streamSize = 269;
+
+        double[] expected = fillPercentHolderWith100();
+        runWithSize(streamSize);
+        assertEqualsForPercentHolder(expected);
+    }
+
+    private void runWithSize(int streamSize) throws Exception {
+        float currentPercent = 0;
+        setupPercentHolder(streamSize);
+        for (int currentIndex = 0; currentIndex < streamSize; currentIndex++) {
+            currentPercent = invokeBulkImportProgress(currentIndex + 1, streamSize, currentPercent);
+        }
+    }
+
+    private float invokeBulkImportProgress(int currentIndex, int streamSize, float currentPercent) throws Exception {
+        return BulkImporterImpl.updateImportProgress(log, currentIndex, streamSize, currentPercent, "additional info");
+    }
+
+    private double[] fillPercentHolderWith100() {
+        double start = 1;
+        double expected[] = new double[MAX_PERCENT];
+        for (int i = 0; i < expected.length; i++) {
+            expected[i] = start;
+            start ++;
+        }
+        return expected;
+    }
+}


[5/5] atlas git commit: ATLAS-2251: restored bunch of deleted tests

Posted by ma...@apache.org.
ATLAS-2251: restored bunch of deleted tests


Project: http://git-wip-us.apache.org/repos/asf/atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/042fc557
Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/042fc557
Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/042fc557

Branch: refs/heads/ATLAS-2251
Commit: 042fc55755e17b3b0112a7a08d30c296300b95d9
Parents: 5f40541
Author: Madhan Neethiraj <ma...@apache.org>
Authored: Thu Nov 9 21:44:26 2017 -0800
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Thu Nov 9 21:44:26 2017 -0800

----------------------------------------------------------------------
 .../org/apache/atlas/query/QueryParser.java     |   11 +-
 .../impexp/AtlasImportRequestTest.java          |  145 +++
 .../repository/impexp/ExportServiceTest.java    |  358 ++++++
 .../repository/impexp/ImportServiceTest.java    |  224 ++++
 .../impexp/ImportServiceTestUtils.java          |  116 ++
 .../impexp/ImportTransformerJSONTest.java       |   47 +
 .../impexp/ImportTransformerTest.java           |  131 +++
 .../repository/impexp/ImportTransformsTest.java |  151 +++
 .../impexp/TypeAttributeDifferenceTest.java     |  150 +++
 .../atlas/repository/impexp/UniqueListTest.java |   69 ++
 .../impexp/ZipFileResourceTestUtils.java        |  220 ++++
 .../atlas/repository/impexp/ZipSinkTest.java    |  210 ++++
 .../atlas/repository/impexp/ZipSourceTest.java  |  189 ++++
 .../store/graph/AtlasTypeDefGraphStoreTest.java |  644 +++++++++++
 .../graph/v1/AtlasEntityDefStoreV1Test.java     |   73 ++
 ...AtlasEntityStoreV1BulkImportPercentTest.java |  167 +++
 .../store/graph/v1/AtlasEntityStoreV1Test.java  | 1043 ++++++++++++++++++
 .../v1/AtlasRelationshipDefStoreV1Test.java     |  330 ++++++
 .../AtlasRelationshipStoreHardDeleteV1Test.java |  112 ++
 .../AtlasRelationshipStoreSoftDeleteV1Test.java |  116 ++
 .../graph/v1/AtlasRelationshipStoreV1Test.java  |  623 +++++++++++
 .../InverseReferenceUpdateHardDeleteV1Test.java |   75 ++
 .../InverseReferenceUpdateSoftDeleteV1Test.java |   78 ++
 .../graph/v1/InverseReferenceUpdateV1Test.java  |  374 +++++++
 .../userprofile/UserProfileServiceTest.java     |  280 +++++
 .../atlas/services/MetricsServiceTest.java      |  123 +++
 .../utils/ObjectUpdateSynchronizerTest.java     |  218 ++++
 .../org/apache/atlas/util/RestUtilsTest.java    |  195 ++++
 28 files changed, 6471 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/main/java/org/apache/atlas/query/QueryParser.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/query/QueryParser.java b/repository/src/main/java/org/apache/atlas/query/QueryParser.java
index be2d9b1..1e5e5ff 100644
--- a/repository/src/main/java/org/apache/atlas/query/QueryParser.java
+++ b/repository/src/main/java/org/apache/atlas/query/QueryParser.java
@@ -19,11 +19,20 @@ package org.apache.atlas.query;
 
 import org.apache.atlas.query.Expressions.Expression;
 
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
 
 
 public class QueryParser {
+    private static final Set<String> RESERVED_KEYWORDS =
+            new HashSet<>(Arrays.asList("[", "]", "(", ")", "=", "<", ">", "!=", "<=", ">=", ",", "and", "or", "+", "-",
+                                        "*", "/", ".", "select", "from", "where", "groupby", "loop", "isa", "is", "has",
+                                        "as", "times", "withPath", "limit", "offset", "orderby", "count", "max", "min",
+                                        "sum", "by", "order", "like"));
+
     public static boolean isKeyword(String word) {
-        return false; // TODO:
+        return RESERVED_KEYWORDS.contains(word);
     }
 
     public static Expression apply(String queryStr, QueryParams params) {

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/AtlasImportRequestTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/AtlasImportRequestTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/AtlasImportRequestTest.java
new file mode 100644
index 0000000..b70b181
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/AtlasImportRequestTest.java
@@ -0,0 +1,145 @@
+/**
+ * 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.impexp;
+
+import org.apache.atlas.model.impexp.AtlasImportRequest;
+import org.apache.atlas.type.AtlasType;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+public class AtlasImportRequestTest {
+    @Test
+    public void serializeAtlasImportRequstFromJsonWithEmptyOptions() {
+        String jsonData = "{ \"options\": {} }";
+
+        AtlasImportRequest request = AtlasType.fromJson(jsonData, AtlasImportRequest.class);
+
+        assertNotNull(request);
+        assertNotNull(request.getOptions());
+        assertNull(request.getOptions().get(AtlasImportRequest.TRANSFORMS_KEY));
+
+        ImportTransforms tr = ImportTransforms.fromJson(request.getOptions().get(AtlasImportRequest.TRANSFORMS_KEY));
+
+        assertNull(tr);
+    }
+
+    @Test
+    public void serializeOptions_VerifyAccessors() {
+        String guid = "\"abcd\"";
+        String pos = "\"1\"";
+        String trueVal = "\"true\"";
+
+        String jsonData = "{ \"options\": " +
+                "               {" +
+                "\"startGuid\":" + guid + "," +
+                "\"startPosition\":" + pos + "," +
+                "\"updateTypeDefinition\":" + trueVal +
+                "}" +
+                "}";
+
+        AtlasImportRequest request = AtlasType.fromJson(jsonData, AtlasImportRequest.class);
+
+        assertNotNull(request);
+        assertNotNull(request.getStartGuid());
+        assertNotNull(request.getStartPosition());
+        assertNotNull(request.getUpdateTypeDefs());
+
+        assertEquals(request.getStartGuid(), guid.replace("\"", ""));
+        assertEquals(request.getStartPosition(), pos.replace("\"", ""));
+        assertEquals(request.getUpdateTypeDefs(), trueVal.replace("\"", ""));
+    }
+
+    @Test
+    public void optionsDefaultsTest() {
+        String jsonData = "{ \"options\": " +
+                "               {" +
+                    "}" +
+                "}";
+
+        AtlasImportRequest request = AtlasType.fromJson(jsonData, AtlasImportRequest.class);
+
+        assertNotNull(request);
+        assertNull(request.getStartGuid());
+        assertNull(request.getStartPosition());
+        assertNull(request.getUpdateTypeDefs());
+    }
+
+    @Test
+    public void serializeAtlasImportRequstFromJsonWithEmptyTransforms() {
+        String jsonData = "{ \"options\": { \"transforms\": \"{ }\" } }";
+
+        AtlasImportRequest request = AtlasType.fromJson(jsonData, AtlasImportRequest.class);
+
+        assertNotNull(request);
+        assertNotNull(request.getOptions());
+        assertNotNull(request.getOptions().get(AtlasImportRequest.TRANSFORMS_KEY));
+
+        ImportTransforms tr = ImportTransforms.fromJson(request.getOptions().get(AtlasImportRequest.TRANSFORMS_KEY));
+
+        assertNotNull(tr);
+        assertNotNull(tr.getTransforms());
+        assertEquals(tr.getTransforms().size(), 0);
+    }
+
+    @Test
+    public void serializeAtlasImportRequstFromJsonWith1Transform() {
+        String jsonData = "{ \"options\": { \"transforms\": \"{ \\\"hive_db\\\": { \\\"qualifiedName\\\": [ \\\"replace:@cl1:@cl2\\\" ] } }\" } }";
+
+        AtlasImportRequest request = AtlasType.fromJson(jsonData, AtlasImportRequest.class);
+
+        assertNotNull(request);
+        assertNotNull(request.getOptions());
+        assertNotNull(request.getOptions().get(AtlasImportRequest.TRANSFORMS_KEY));
+
+        ImportTransforms tr = ImportTransforms.fromJson(request.getOptions().get(AtlasImportRequest.TRANSFORMS_KEY));
+
+        assertNotNull(tr);
+        assertNotNull(tr.getTransforms());
+        assertEquals(tr.getTransforms().size(), 1);
+        assertTrue(tr.getTransforms().containsKey("hive_db"));
+        assertEquals(tr.getTransforms("hive_db").entrySet().size(), 1);
+        assertTrue(tr.getTransforms("hive_db").containsKey("qualifiedName"));
+        assertEquals(tr.getTransforms("hive_db").get("qualifiedName").size(), 1);
+    }
+
+    @Test
+    public void serializeAtlasImportRequstFromJson() {
+        String jsonData = "{ \"options\": { \"transforms\": \"{ \\\"hive_db\\\": { \\\"qualifiedName\\\": [ \\\"replace:@cl1:@cl2\\\" ] }, \\\"hive_table\\\": { \\\"qualifiedName\\\": [ \\\"lowercase\\\", \\\"replace:@cl1:@cl2\\\" ] } }\" } } }";
+
+        AtlasImportRequest request = AtlasType.fromJson(jsonData, AtlasImportRequest.class);
+
+        assertNotNull(request);
+        assertNotNull(request.getOptions());
+        assertNotNull(request.getOptions().get(AtlasImportRequest.TRANSFORMS_KEY));
+
+        ImportTransforms tr = ImportTransforms.fromJson(request.getOptions().get(AtlasImportRequest.TRANSFORMS_KEY));
+
+        assertNotNull(tr);
+        assertNotNull(tr.getTransforms());
+        assertEquals(tr.getTransforms().size(), 2);
+        assertTrue(tr.getTransforms().containsKey("hive_db"));
+        assertEquals(tr.getTransforms("hive_db").entrySet().size(), 1);
+        assertTrue(tr.getTransforms("hive_db").containsKey("qualifiedName"));
+        assertEquals(tr.getTransforms("hive_db").get("qualifiedName").size(), 1);
+        assertTrue(tr.getTransforms().containsKey("hive_table"));
+        assertEquals(tr.getTransforms("hive_table").entrySet().size(), 1);
+        assertTrue(tr.getTransforms("hive_table").containsKey("qualifiedName"));
+        assertEquals(tr.getTransforms("hive_table").get("qualifiedName").size(), 2);
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/ExportServiceTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ExportServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ExportServiceTest.java
new file mode 100644
index 0000000..2a8bdfa
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ExportServiceTest.java
@@ -0,0 +1,358 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.impexp;
+
+
+import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.TestUtilsV2;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.impexp.AtlasExportRequest;
+import org.apache.atlas.model.impexp.AtlasExportResult;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.model.typedef.AtlasTypesDef;
+import org.apache.atlas.repository.graph.AtlasGraphProvider;
+import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
+import org.apache.atlas.repository.store.graph.v1.AtlasEntityChangeNotifier;
+import org.apache.atlas.repository.store.graph.v1.AtlasEntityStoreV1;
+import org.apache.atlas.repository.store.graph.v1.AtlasEntityStream;
+import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
+import org.apache.atlas.repository.store.graph.v1.EntityGraphMapper;
+import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1;
+import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import javax.inject.Inject;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.Mockito.mock;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+@Guice(modules = TestModules.TestOnlyModule.class)
+public class ExportServiceTest {
+    private static final Logger LOG = LoggerFactory.getLogger(ExportServiceTest.class);
+
+    @Inject
+    AtlasTypeRegistry typeRegistry;
+
+    @Inject
+    private AtlasTypeDefStore typeDefStore;
+
+    @Inject
+    private EntityGraphMapper graphMapper;
+    @Inject
+    ExportService exportService;
+    private DeleteHandlerV1 deleteHandler = mock(SoftDeleteHandlerV1.class);;
+    private AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class);
+    private AtlasEntityStoreV1 entityStore;
+
+    @BeforeTest
+    public void setupTest() {
+        RequestContextV1.clear();
+        RequestContextV1.get().setUser(TestUtilsV2.TEST_USER);
+    }
+
+    @BeforeClass
+    public void setupSampleData() throws AtlasBaseException {
+        entityStore = new AtlasEntityStoreV1(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper);;
+
+        AtlasTypesDef sampleTypes = TestUtilsV2.defineDeptEmployeeTypes();
+        AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(sampleTypes, typeRegistry);
+
+        if (!typesToCreate.isEmpty()) {
+            typeDefStore.createTypesDef(typesToCreate);
+        }
+
+        AtlasEntity.AtlasEntitiesWithExtInfo  hrDept = TestUtilsV2.createDeptEg2();
+
+        AtlasEntityStream entityStream = new AtlasEntityStream(hrDept);
+        entityStore.createOrUpdate(entityStream, false);
+        LOG.debug("==> setupSampleData: ", AtlasEntity.dumpObjects(hrDept.getEntities(), null).toString());
+    }
+
+    @AfterClass
+    public void clear() {
+        AtlasGraphProvider.cleanup();
+    }
+
+    private AtlasExportRequest getRequestForFullFetch() {
+        AtlasExportRequest request = new AtlasExportRequest();
+
+        List<AtlasObjectId> itemsToExport = new ArrayList<>();
+        itemsToExport.add(new AtlasObjectId("hive_db", "qualifiedName", "default@cl1"));
+        request.setItemsToExport(itemsToExport);
+
+        return request;
+    }
+
+    private AtlasExportRequest getRequestForDept(boolean addFetchType, String fetchTypeValue, boolean addMatchType, String matchTypeValue) {
+        AtlasExportRequest request = new AtlasExportRequest();
+
+        List<AtlasObjectId> itemsToExport = new ArrayList<>();
+        itemsToExport.add(new AtlasObjectId("Department", "name", "hr"));
+        request.setItemsToExport(itemsToExport);
+
+        setOptionsMap(request, addFetchType, fetchTypeValue, addMatchType, matchTypeValue);
+        return request;
+    }
+
+    private AtlasExportRequest getRequestForEmployee() {
+        AtlasExportRequest request = new AtlasExportRequest();
+
+        List<AtlasObjectId> itemsToExport = new ArrayList<>();
+        itemsToExport.add(new AtlasObjectId("Employee", "name", "Max"));
+        request.setItemsToExport(itemsToExport);
+
+        setOptionsMap(request, true, "CONNECTED", false, "");
+        return request;
+    }
+
+    private void setOptionsMap(AtlasExportRequest request,
+                               boolean addFetchType, String fetchTypeValue, boolean addMatchType, String matchTypeValue) {
+        Map<String, Object> optionsMap = null;
+        if(addFetchType) {
+            if(optionsMap == null) {
+                optionsMap = new HashMap<>();
+            }
+
+            optionsMap.put("fetchType", fetchTypeValue);
+            request.setOptions(optionsMap);
+        }
+
+        if(addMatchType) {
+            if(optionsMap == null) {
+                optionsMap = new HashMap<>();
+            }
+
+            optionsMap.put("matchType", matchTypeValue);
+        }
+
+        if(optionsMap != null) {
+            request.setOptions(optionsMap);
+        }
+    }
+
+    private ZipSource runExportWithParameters(AtlasExportRequest request) throws AtlasBaseException, IOException {
+        final String requestingIP = "1.0.0.0";
+        final String hostName = "localhost";
+        final String userName = "admin";
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ZipSink zipSink = new ZipSink(baos);
+        AtlasExportResult result = exportService.run(zipSink, request, userName, hostName, requestingIP);
+
+        zipSink.close();
+
+        ByteArrayInputStream bis = new ByteArrayInputStream(baos.toByteArray());
+        ZipSource zipSource = new ZipSource(bis);
+        return zipSource;
+    }
+
+    @Test
+    public void exportType_Succeeds() throws AtlasBaseException, FileNotFoundException {
+        String requestingIP = "1.0.0.0";
+        String hostName = "root";
+
+        AtlasExportRequest request = getRequestForFullFetch();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ZipSink zipSink = new ZipSink(baos);
+        AtlasExportResult result = exportService.run(zipSink, request, "admin", hostName, requestingIP);
+
+        assertNotNull(exportService);
+        assertEquals(result.getHostName(), hostName);
+        assertEquals(result.getClientIpAddress(), requestingIP);
+        assertEquals(request, result.getRequest());
+    }
+
+    @Test
+    public void requestingEntityNotFound_NoData() throws AtlasBaseException, IOException {
+        String requestingIP = "1.0.0.0";
+        String hostName = "root";
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ZipSink zipSink = new ZipSink(baos);
+        AtlasExportResult result = exportService.run(
+                zipSink, getRequestForFullFetch(), "admin", hostName, requestingIP);
+
+        Assert.assertNull(result.getData());
+
+        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+        ZipSource zipSource = new ZipSource(bais);
+
+        assertNotNull(exportService);
+        assertNotNull(zipSource.getCreationOrder());
+        Assert.assertFalse(zipSource.hasNext());
+    }
+
+    @Test
+    public void requestingEntityFoundDefaultFetch_ContainsData() throws Exception {
+        ZipSource source = runExportWithParameters(
+                getRequestForDept(false, "", false, ""));
+        verifyExportForHrData(source);
+    }
+
+    @Test
+    public void requestingHrEntityWithMatchTypeContains_ContainsData() throws Exception {
+        ZipSource source = runExportWithParameters(
+                getRequestForDept(false, "", true, "CONTAINS"));
+        verifyExportForHrData(source);
+    }
+
+    @Test
+    public void requestingHrEntityWithMatchTypeEndsWith_ContainsData() throws Exception {
+        ZipSource source = runExportWithParameters(
+                getRequestForDept(false, "", true, "ENDSWITH"));
+        verifyExportForHrData(source);
+    }
+
+    @Test
+    public void requestingDeptEntityFoundFullFetch_ContainsData() throws Exception {
+        ZipSource source = runExportWithParameters(
+                getRequestForDept(true, "FULL", false, ""));
+        verifyExportForHrData(source);
+    }
+
+    @Test
+    public void requestingDeptEntityFoundConnectedFetch_ContainsData() throws Exception {
+        ZipSource source = runExportWithParameters(
+                getRequestForDept(true, "CONNECTED", false, ""));
+        verifyExportForHrDataForConnected(source);
+    }
+
+    @Test
+    public void requestingEmployeeEntityFoundConnectedFetch_ContainsData() throws Exception {
+        ZipSource zipSource = runExportWithParameters(getRequestForEmployee());
+        verifyExportForEmployeeData(zipSource);
+    }
+
+    @Test
+    public void verifyOverallStatus() throws Exception {
+
+//        ExportService service = new ExportService(typeRegistry);
+        assertEquals(AtlasExportResult.OperationStatus.FAIL, exportService.getOverallOperationStatus());
+
+        assertEquals(AtlasExportResult.OperationStatus.SUCCESS, exportService.getOverallOperationStatus(AtlasExportResult.OperationStatus.SUCCESS));
+
+        assertEquals(AtlasExportResult.OperationStatus.SUCCESS, exportService.getOverallOperationStatus(
+                                AtlasExportResult.OperationStatus.SUCCESS,
+                                AtlasExportResult.OperationStatus.SUCCESS,
+                                AtlasExportResult.OperationStatus.SUCCESS));
+
+        assertEquals(AtlasExportResult.OperationStatus.PARTIAL_SUCCESS, exportService.getOverallOperationStatus(
+                AtlasExportResult.OperationStatus.FAIL,
+                AtlasExportResult.OperationStatus.PARTIAL_SUCCESS,
+                AtlasExportResult.OperationStatus.SUCCESS));
+
+        assertEquals(AtlasExportResult.OperationStatus.PARTIAL_SUCCESS, exportService.getOverallOperationStatus(
+                AtlasExportResult.OperationStatus.FAIL,
+                AtlasExportResult.OperationStatus.FAIL,
+                AtlasExportResult.OperationStatus.PARTIAL_SUCCESS));
+
+        assertEquals(AtlasExportResult.OperationStatus.FAIL, exportService.getOverallOperationStatus(
+                AtlasExportResult.OperationStatus.FAIL,
+                AtlasExportResult.OperationStatus.FAIL,
+                AtlasExportResult.OperationStatus.FAIL));
+    }
+
+    @Test
+    public void requestingExportOfNonExistentEntity_ReturnsFailure() throws Exception {
+        AtlasExportRequest request = getRequestForEmployee();
+        tamperEmployeeRequest(request);
+        ZipSource zipSource = runExportWithParameters(request);
+
+        assertNotNull(zipSource.getCreationOrder());
+        assertEquals(zipSource.getCreationOrder().size(), 0);
+        assertEquals(AtlasExportResult.OperationStatus.FAIL, zipSource.getExportResult().getOperationStatus());
+    }
+
+    private void tamperEmployeeRequest(AtlasExportRequest request) {
+        AtlasObjectId objectId = request.getItemsToExport().get(0);
+        objectId.getUniqueAttributes().remove("name");
+        objectId.getUniqueAttributes().put("qualifiedName", "XXX@121");
+    }
+
+    private void verifyExportForEmployeeData(ZipSource zipSource) throws AtlasBaseException {
+        final List<String> expectedEntityTypes = Arrays.asList(new String[]{"Manager", "Employee", "Department"});
+
+        assertNotNull(zipSource.getCreationOrder());
+        assertEquals(zipSource.getCreationOrder().size(), 2);
+        assertTrue(zipSource.hasNext());
+
+        while (zipSource.hasNext()) {
+            AtlasEntity entity = zipSource.next();
+
+            assertNotNull(entity);
+            assertEquals(AtlasEntity.Status.ACTIVE, entity.getStatus());
+            assertTrue(expectedEntityTypes.contains(entity.getTypeName()));
+        }
+
+        verifyTypeDefs(zipSource);
+    }
+
+    private void verifyExportForHrData(ZipSource zipSource) throws IOException, AtlasBaseException {
+        assertNotNull(zipSource.getCreationOrder());
+        assertTrue(zipSource.getCreationOrder().size() == 1);
+        assertTrue(zipSource.hasNext());
+
+        AtlasEntity entity = zipSource.next();
+
+        assertNotNull(entity);
+        assertTrue(entity.getTypeName().equals("Department"));
+        assertEquals(entity.getStatus(), AtlasEntity.Status.ACTIVE);
+        verifyTypeDefs(zipSource);
+    }
+
+    private void verifyExportForHrDataForConnected(ZipSource zipSource) throws IOException, AtlasBaseException {
+        assertNotNull(zipSource.getCreationOrder());
+        assertTrue(zipSource.getCreationOrder().size() == 2);
+        assertTrue(zipSource.hasNext());
+
+        AtlasEntity entity = zipSource.next();
+
+        assertNotNull(entity);
+        assertTrue(entity.getTypeName().equals("Department"));
+        assertEquals(entity.getStatus(), AtlasEntity.Status.ACTIVE);
+        verifyTypeDefs(zipSource);
+    }
+
+    private void verifyTypeDefs(ZipSource zipSource) throws AtlasBaseException {
+        assertEquals(zipSource.getTypesDef().getEnumDefs().size(), 1);
+        assertEquals(zipSource.getTypesDef().getClassificationDefs().size(), 0);
+        assertEquals(zipSource.getTypesDef().getStructDefs().size(), 1);
+        assertEquals(zipSource.getTypesDef().getEntityDefs().size(), 4);
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java
new file mode 100644
index 0000000..b24774d
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java
@@ -0,0 +1,224 @@
+/**
+ * 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.impexp;
+
+import com.google.inject.Inject;
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.TestUtilsV2;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.impexp.AtlasImportRequest;
+import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasClassificationType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.ITestContext;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+@Guice(modules = TestModules.TestOnlyModule.class)
+public class ImportServiceTest {
+    private static final Logger LOG = LoggerFactory.getLogger(ImportServiceTest.class);
+    private final ImportService importService;
+
+    @Inject
+    AtlasTypeRegistry typeRegistry;
+
+    @Inject
+    private AtlasTypeDefStore typeDefStore;
+
+    @Inject
+    public ImportServiceTest(ImportService importService) {
+        this.importService = importService;
+    }
+
+    @BeforeTest
+    public void setupTest() {
+        RequestContextV1.clear();
+        RequestContextV1.get().setUser(TestUtilsV2.TEST_USER);
+    }
+
+    @DataProvider(name = "sales")
+    public static Object[][] getDataFromQuickStart_v1_Sales(ITestContext context) throws IOException {
+        return getZipSource("sales-v1-full.zip");
+    }
+
+    @Test(dataProvider = "sales")
+    public void importDB1(ZipSource zipSource) throws AtlasBaseException, IOException {
+        loadBaseModel();
+        runAndVerifyQuickStart_v1_Import(importService, zipSource);
+    }
+
+    @DataProvider(name = "reporting")
+    public static Object[][] getDataFromReporting() throws IOException {
+        return getZipSource("reporting-v1-full.zip");
+    }
+
+    @Test(dataProvider = "reporting")
+    public void importDB2(ZipSource zipSource) throws AtlasBaseException, IOException {
+        loadBaseModel();
+        runAndVerifyQuickStart_v1_Import(importService, zipSource);
+    }
+
+    private void loadBaseModel() throws IOException, AtlasBaseException {
+        loadModelFromJson("0000-Area0/0010-base_model.json", typeDefStore, typeRegistry);
+    }
+
+    @DataProvider(name = "logging")
+    public static Object[][] getDataFromLogging(ITestContext context) throws IOException {
+        return getZipSource("logging-v1-full.zip");
+    }
+
+    @Test(dataProvider = "logging")
+    public void importDB3(ZipSource zipSource) throws AtlasBaseException, IOException {
+        loadBaseModel();
+        runAndVerifyQuickStart_v1_Import(importService, zipSource);
+    }
+
+    @DataProvider(name = "salesNewTypeAttrs")
+    public static Object[][] getDataFromSalesNewTypeAttrs(ITestContext context) throws IOException {
+        return getZipSource("salesNewTypeAttrs.zip");
+    }
+
+    @Test(dataProvider = "salesNewTypeAttrs", dependsOnMethods = "importDB1")
+    public void importDB4(ZipSource zipSource) throws AtlasBaseException, IOException {
+        loadBaseModel();
+        runImportWithParameters(importService, getDefaultImportRequest(), zipSource);
+    }
+
+    @DataProvider(name = "salesNewTypeAttrs-next")
+    public static Object[][] getDataFromSalesNewTypeAttrsNext(ITestContext context) throws IOException {
+        return getZipSource("salesNewTypeAttrs-next.zip");
+    }
+
+
+    @Test(dataProvider = "salesNewTypeAttrs-next", dependsOnMethods = "importDB4")
+    public void importDB5(ZipSource zipSource) throws AtlasBaseException, IOException {
+        final String newEnumDefName = "database_action";
+
+        assertNotNull(typeDefStore.getEnumDefByName(newEnumDefName));
+
+        AtlasImportRequest request = getDefaultImportRequest();
+        Map<String, String> options = new HashMap<>();
+        options.put("updateTypeDefinition", "false");
+        request.setOptions(options);
+
+        runImportWithParameters(importService, request, zipSource);
+        assertNotNull(typeDefStore.getEnumDefByName(newEnumDefName));
+        assertEquals(typeDefStore.getEnumDefByName(newEnumDefName).getElementDefs().size(), 4);
+    }
+
+    @Test(dataProvider = "salesNewTypeAttrs-next", dependsOnMethods = "importDB4")
+    public void importDB6(ZipSource zipSource) throws AtlasBaseException, IOException {
+        final String newEnumDefName = "database_action";
+
+        assertNotNull(typeDefStore.getEnumDefByName(newEnumDefName));
+
+        AtlasImportRequest request = getDefaultImportRequest();
+        Map<String, String> options = new HashMap<>();
+        options.put("updateTypeDefinition", "true");
+        request.setOptions(options);
+
+        runImportWithParameters(importService, request, zipSource);
+        assertNotNull(typeDefStore.getEnumDefByName(newEnumDefName));
+        assertEquals(typeDefStore.getEnumDefByName(newEnumDefName).getElementDefs().size(), 8);
+    }
+
+    @DataProvider(name = "ctas")
+    public static Object[][] getDataFromCtas(ITestContext context) throws IOException {
+        return getZipSource("ctas.zip");
+    }
+
+    @Test(dataProvider = "ctas")
+    public void importCTAS(ZipSource zipSource) throws IOException, AtlasBaseException {
+        loadBaseModel();
+        loadHiveModel();
+
+        runImportWithNoParameters(importService, zipSource);
+    }
+
+    @DataProvider(name = "hdfs_path1")
+    public static Object[][] getDataFromHdfsPath1(ITestContext context) throws IOException {
+        return getZipSource("hdfs_path1.zip");
+    }
+
+
+    @Test(dataProvider = "hdfs_path1", expectedExceptions = AtlasBaseException.class)
+    public void importHdfs_path1(ZipSource zipSource) throws IOException, AtlasBaseException {
+        loadBaseModel();
+        loadFsModel();
+        loadModelFromResourcesJson("tag1.json", typeDefStore, typeRegistry);
+
+        try {
+            runImportWithNoParameters(importService, zipSource);
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.INVALID_IMPORT_ATTRIBUTE_TYPE_CHANGED);
+            AtlasClassificationType tag1 = typeRegistry.getClassificationTypeByName("tag1");
+            assertNotNull(tag1);
+            assertEquals(tag1.getAllAttributes().size(), 2);
+            throw e;
+        }
+    }
+
+    @Test
+    public void importServiceProcessesIOException() {
+        ImportService importService = new ImportService(typeDefStore, typeRegistry, null);
+        AtlasImportRequest req = mock(AtlasImportRequest.class);
+
+        Answer<Map> answer = new Answer<Map>() {
+            @Override
+            public Map answer(InvocationOnMock invocationOnMock) throws Throwable {
+                throw new IOException("file is read only");
+            }
+        };
+
+        when(req.getFileName()).thenReturn("some-file.zip");
+        when(req.getOptions()).thenAnswer(answer);
+
+        try {
+            importService.run(req, "a", "b", "c");
+        }
+        catch (AtlasBaseException ex) {
+            assertEquals(ex.getAtlasErrorCode().getErrorCode(), AtlasErrorCode.INVALID_PARAMETERS.getErrorCode());
+        }
+    }
+
+    private void loadFsModel() throws IOException, AtlasBaseException {
+        loadModelFromJson("1000-Hadoop/1020-fs_model.json", typeDefStore, typeRegistry);
+    }
+
+    private void loadHiveModel() throws IOException, AtlasBaseException {
+        loadModelFromJson("1000-Hadoop/1030-hive_model.json", typeDefStore, typeRegistry);
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTestUtils.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTestUtils.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTestUtils.java
new file mode 100644
index 0000000..7289512
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTestUtils.java
@@ -0,0 +1,116 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.impexp;
+
+import com.google.common.collect.Sets;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.impexp.AtlasExportResult;
+import org.apache.atlas.model.impexp.AtlasImportRequest;
+import org.apache.atlas.model.impexp.AtlasImportResult;
+import org.apache.atlas.model.typedef.AtlasTypesDef;
+import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
+import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.testng.Assert;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class ImportServiceTestUtils {
+
+    public static void verifyImportedEntities(List<String> creationOrder, List<String> processedEntities) {
+        Set<String> lhs = com.google.common.collect.Sets.newHashSet(creationOrder);
+        Set<String> rhs = com.google.common.collect.Sets.newHashSet(processedEntities);
+        Set<String> difference = Sets.difference(lhs, rhs);
+
+        Assert.assertNotNull(difference);
+        Assert.assertEquals(difference.size(), 0);
+    }
+
+    public static void verifyImportedMetrics(AtlasExportResult exportResult, AtlasImportResult importResult) {
+        Map<String, Integer> metricsForCompare = getImportMetricsForCompare(importResult);
+        for (Map.Entry<String, Integer> entry : exportResult.getMetrics().entrySet()) {
+            if(entry.getKey().startsWith("entity") == false ||
+                    entry.getKey().contains("withExtInfo") ||
+                    entry.getKey().contains("Column") ||
+                    entry.getKey().contains("StorageDesc")) continue;
+
+            Assert.assertTrue(metricsForCompare.containsKey(entry.getKey()));
+            Assert.assertEquals(entry.getValue(), metricsForCompare.get(entry.getKey()));
+        }
+    }
+
+    private static Map<String,Integer> getImportMetricsForCompare(AtlasImportResult result) {
+        Map<String, Integer> r = new HashMap<>();
+        for (Map.Entry<String, Integer> entry : result.getMetrics().entrySet()) {
+            r.put(entry.getKey().replace(":updated", "").replace(":created", ""), entry.getValue());
+        }
+
+        return r;
+    }
+
+
+    public static void loadModelFromJson(String fileName, AtlasTypeDefStore typeDefStore, AtlasTypeRegistry typeRegistry) throws IOException, AtlasBaseException {
+        AtlasTypesDef typesFromJson = getAtlasTypesDefFromFile(fileName);
+        createTypesAsNeeded(typesFromJson, typeDefStore, typeRegistry);
+    }
+
+    private static void createTypesAsNeeded(AtlasTypesDef typesFromJson, AtlasTypeDefStore typeDefStore, AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
+        AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(typesFromJson, typeRegistry);
+
+        if (!typesToCreate.isEmpty()) {
+            typeDefStore.createTypesDef(typesToCreate);
+        }
+    }
+
+    private static AtlasTypesDef getAtlasTypesDefFromFile(String fileName) throws IOException {
+        String sampleTypes = ZipFileResourceTestUtils.getModelJson(fileName);
+        return AtlasType.fromJson(sampleTypes, AtlasTypesDef.class);
+    }
+
+    public static AtlasImportRequest getDefaultImportRequest() {
+        return new AtlasImportRequest();
+    }
+
+
+    public static AtlasImportResult runImportWithParameters(ImportService importService, AtlasImportRequest request, ZipSource source) throws AtlasBaseException, IOException {
+        final String requestingIP = "1.0.0.0";
+        final String hostName = "localhost";
+        final String userName = "admin";
+
+        AtlasImportResult result = importService.run(source, request, userName, hostName, requestingIP);
+        Assert.assertEquals(result.getOperationStatus(), AtlasImportResult.OperationStatus.SUCCESS);
+        return result;
+    }
+
+    public static void runAndVerifyQuickStart_v1_Import(ImportService importService, ZipSource zipSource) throws AtlasBaseException, IOException {
+        AtlasExportResult exportResult = zipSource.getExportResult();
+        List<String> creationOrder = zipSource.getCreationOrder();
+
+        AtlasImportRequest request = getDefaultImportRequest();
+        AtlasImportResult result = runImportWithParameters(importService, request, zipSource);
+
+        Assert.assertNotNull(result);
+        verifyImportedMetrics(exportResult, result);
+        verifyImportedEntities(creationOrder, result.getProcessedEntities());
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformerJSONTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformerJSONTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformerJSONTest.java
new file mode 100644
index 0000000..7044e71
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformerJSONTest.java
@@ -0,0 +1,47 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.impexp;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+import static org.testng.Assert.*;
+
+public class ImportTransformerJSONTest {
+
+
+    @Test
+    public void createAtlasImportTransformFromJson() throws Exception {
+        String hiveTableType  = "hive_table";
+        String qualifiedName  = "qualifiedName";
+        String jsonTransforms = "{ \"hive_table\": { \"qualifiedName\":[ \"lowercase\", \"replace:@cl1:@cl2\" ] } }";
+
+        ImportTransforms transforms = ImportTransforms.fromJson(jsonTransforms);
+
+        assertNotNull(transforms);
+        assertEquals(transforms.getTransforms().entrySet().size(), 1);
+        assertEquals(transforms.getTransforms().get(hiveTableType).entrySet().size(), 1);
+        assertEquals(transforms.getTransforms().get(hiveTableType).get(qualifiedName).size(), 2);
+        Assert.assertEquals(transforms.getTransforms().get(hiveTableType).get(qualifiedName).get(0).getTransformType(), "lowercase");
+        assertEquals(transforms.getTransforms().get(hiveTableType).get(qualifiedName).get(1).getTransformType(), "replace");
+        assertTrue(transforms.getTransforms().get(hiveTableType).get(qualifiedName).get(1) instanceof ImportTransformer.Replace);
+        assertEquals(((ImportTransformer.Replace)transforms.getTransforms().get(hiveTableType).get(qualifiedName).get(1)).getToFindStr(), "@cl1");
+        assertEquals(((ImportTransformer.Replace)transforms.getTransforms().get(hiveTableType).get(qualifiedName).get(1)).getReplaceStr(), "@cl2");
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformerTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformerTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformerTest.java
new file mode 100644
index 0000000..7ce34c8
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformerTest.java
@@ -0,0 +1,131 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.impexp;
+
+import org.apache.atlas.exception.AtlasBaseException;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class ImportTransformerTest {
+
+    @Test
+    public void createWithCorrectParameters() throws AtlasBaseException, IllegalAccessException {
+        String param1 = "@cl1";
+        String param2 = "@cl2";
+
+        ImportTransformer e = ImportTransformer.getTransformer(String.format("%s:%s:%s", "replace", param1, param2));
+
+        assertTrue(e instanceof ImportTransformer.Replace);
+        assertEquals(((ImportTransformer.Replace)e).getToFindStr(), param1);
+        assertEquals(((ImportTransformer.Replace)e).getReplaceStr(), param2);
+    }
+
+    @Test
+    public void createSeveralWithCorrectParameters() throws AtlasBaseException, IllegalAccessException {
+        String param1 = "@cl1";
+        String param2 = "@cl2";
+
+        ImportTransformer e1 = ImportTransformer.getTransformer(String.format("%s:%s:%s", "replace", param1, param2));
+        ImportTransformer e2 = ImportTransformer.getTransformer(String.format("replace:tt1:tt2"));
+
+        assertTrue(e1 instanceof ImportTransformer.Replace);
+        assertEquals(((ImportTransformer.Replace)e1).getToFindStr(), param1);
+        assertEquals(((ImportTransformer.Replace)e1).getReplaceStr(), param2);
+
+        assertTrue(e2 instanceof ImportTransformer.Replace);
+        assertEquals(((ImportTransformer.Replace)e2).getToFindStr(), "tt1");
+        assertEquals(((ImportTransformer.Replace)e2).getReplaceStr(), "tt2");
+    }
+
+    @Test
+    public void createWithDefaultParameters() throws AtlasBaseException {
+        ImportTransformer e1 = ImportTransformer.getTransformer("replace:@cl1");
+        ImportTransformer e2 = ImportTransformer.getTransformer("replace");
+
+        assertTrue(e1 instanceof ImportTransformer.Replace);
+        assertEquals(((ImportTransformer.Replace)e1).getToFindStr(), "@cl1");
+        assertEquals(((ImportTransformer.Replace)e1).getReplaceStr(), "");
+
+        assertTrue(e2 instanceof ImportTransformer.Replace);
+        assertEquals(((ImportTransformer.Replace)e2).getToFindStr(), "");
+        assertEquals(((ImportTransformer.Replace)e2).getReplaceStr(), "");
+    }
+
+    @Test
+    public void applyLowercaseTransformer() throws AtlasBaseException {
+        ImportTransformer e = ImportTransformer.getTransformer("lowercase");
+
+        assertEquals(e.apply("@CL1"), "@cl1");
+        assertEquals(e.apply("@cl1"), "@cl1");
+        assertEquals(e.apply(""), ""); // empty string
+        assertEquals(e.apply(null), null); // null value: no change
+        assertEquals(e.apply(Integer.valueOf(5)), Integer.valueOf(5)); // non-string value: no change
+    }
+
+    @Test
+    public void applyUppercaseTransformer() throws AtlasBaseException {
+        ImportTransformer e = ImportTransformer.getTransformer("uppercase");
+
+        assertEquals(e.apply("@CL1"), "@CL1");
+        assertEquals(e.apply("@cl1"), "@CL1");
+        assertEquals(e.apply(""), ""); // empty string
+        assertEquals(e.apply(null), null); // null value: no change
+        assertEquals(e.apply(Integer.valueOf(5)), Integer.valueOf(5)); // non-string value: no change
+    }
+
+    @Test
+    public void applyReplaceTransformer1() throws AtlasBaseException {
+        ImportTransformer e = ImportTransformer.getTransformer("replace:@cl1:@cl2");
+
+        assertEquals(e.apply("@cl1"), "@cl2");
+        assertEquals(e.apply("default@cl1"), "default@cl2");
+        assertEquals(e.apply("@cl11"), "@cl21");
+        assertEquals(e.apply("@cl2"), "@cl2");
+        assertEquals(e.apply(""), ""); // empty string
+        assertEquals(e.apply(null), null); // null value
+        assertEquals(e.apply(Integer.valueOf(5)), Integer.valueOf(5)); // non-string value: no change
+    }
+
+    @Test
+    public void applyReplaceTransformer2() throws AtlasBaseException {
+        ImportTransformer e = ImportTransformer.getTransformer("replace:@cl1");
+
+        assertEquals(e.apply("@cl1"), "");
+        assertEquals(e.apply("default@cl1"), "default");
+        assertEquals(e.apply("@cl11"), "1");
+        assertEquals(e.apply("@cl2"), "@cl2");
+        assertEquals(e.apply(""), ""); // empty string
+        assertEquals(e.apply(null), null); // null value
+        assertEquals(e.apply(Integer.valueOf(5)), Integer.valueOf(5)); // non-string value: no change
+    }
+
+    @Test
+    public void applyReplaceTransformer3() throws AtlasBaseException {
+        ImportTransformer e = ImportTransformer.getTransformer("replace");
+
+        assertEquals(e.apply("@cl1"), "@cl1");
+        assertEquals(e.apply("default@cl1"), "default@cl1");
+        assertEquals(e.apply("@cl11"), "@cl11");
+        assertEquals(e.apply("@cl2"), "@cl2");
+        assertEquals(e.apply(""), ""); // empty string
+        assertEquals(e.apply(null), null); // null value
+        assertEquals(e.apply(Integer.valueOf(5)), Integer.valueOf(5)); // non-string value: no change
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformsTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformsTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformsTest.java
new file mode 100644
index 0000000..ccedeb1
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformsTest.java
@@ -0,0 +1,151 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.impexp;
+
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+public class ImportTransformsTest {
+    private final String qualifiedName  = "qualifiedName";
+    private final String lowerCaseCL1   = "@cl1";
+    private final String lowerCaseCL2   = "@cl2";
+    private final String jsonTransforms = "{ \"hive_table\": { \"qualifiedName\":[ \"lowercase\", \"replace:@cl1:@cl2\" ] } }";
+
+    private ImportTransforms transform;
+
+    @BeforeTest
+    public void setup() throws AtlasBaseException {
+        transform = ImportTransforms.fromJson(jsonTransforms);
+    }
+
+    @Test
+    public void transformEntityWith2Transforms() throws AtlasBaseException {
+        AtlasEntity entity    = getHiveTableAtlasEntity();
+        String      attrValue = (String) entity.getAttribute(qualifiedName);
+
+        transform.apply(entity);
+
+        assertEquals(entity.getAttribute(qualifiedName), applyDefaultTransform(attrValue));
+    }
+
+    @Test
+    public void transformEntityWithExtInfo() throws AtlasBaseException {
+        addColumnTransform(transform);
+
+        AtlasEntityWithExtInfo entityWithExtInfo = getAtlasEntityWithExtInfo();
+        AtlasEntity            entity            = entityWithExtInfo.getEntity();
+        String                 attrValue         = (String) entity.getAttribute(qualifiedName);
+        String[]               expectedValues    = getExtEntityExpectedValues(entityWithExtInfo);
+
+        transform.apply(entityWithExtInfo);
+
+        assertEquals(entityWithExtInfo.getEntity().getAttribute(qualifiedName), applyDefaultTransform(attrValue));
+
+        for (int i = 0; i < expectedValues.length; i++) {
+            assertEquals(entityWithExtInfo.getReferredEntities().get(Integer.toString(i)).getAttribute(qualifiedName), expectedValues[i]);
+        }
+    }
+
+    @Test
+    public void transformEntityWithExtInfoNullCheck() throws AtlasBaseException {
+        addColumnTransform(transform);
+
+        AtlasEntityWithExtInfo entityWithExtInfo = getAtlasEntityWithExtInfo();
+
+        entityWithExtInfo.setReferredEntities(null);
+
+        AtlasEntityWithExtInfo transformedEntityWithExtInfo = transform.apply(entityWithExtInfo);
+
+        assertNotNull(transformedEntityWithExtInfo);
+        assertEquals(entityWithExtInfo.getEntity().getGuid(), transformedEntityWithExtInfo.getEntity().getGuid());
+    }
+
+    private String[] getExtEntityExpectedValues(AtlasEntityWithExtInfo entityWithExtInfo) {
+        String[] ret = new String[entityWithExtInfo.getReferredEntities().size()];
+
+        for (int i = 0; i < ret.length; i++) {
+            String attrValue = (String) entityWithExtInfo.getReferredEntities().get(Integer.toString(i)).getAttribute(qualifiedName);
+
+            ret[i] = attrValue.replace(lowerCaseCL1, lowerCaseCL2);
+        }
+
+        return ret;
+    }
+
+    private void addColumnTransform(ImportTransforms transform) throws AtlasBaseException {
+        Map<String, List<ImportTransformer>> tr     = new HashMap<>();
+        List<ImportTransformer>              trList = new ArrayList<>();
+
+        trList.add(ImportTransformer.getTransformer(String.format("replace:%s:%s", lowerCaseCL1, lowerCaseCL2)));
+
+        tr.put(qualifiedName, trList);
+
+        transform.getTransforms().put("hive_column", tr);
+    }
+
+    private String applyDefaultTransform(String attrValue) {
+        return attrValue.toLowerCase().replace(lowerCaseCL1, lowerCaseCL2);
+    }
+
+    private AtlasEntity getHiveTableAtlasEntity() {
+        AtlasEntity entity = new AtlasEntity("hive_table");
+
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put(qualifiedName, "TABLE1.default" + lowerCaseCL1);
+        attributes.put("dbname", "someDB");
+        attributes.put("name", "somename");
+
+        entity.setAttributes(attributes);
+        return entity;
+    }
+
+    private AtlasEntity getHiveColumnAtlasEntity(int index) {
+        AtlasEntity entity = new AtlasEntity("hive_column");
+
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put(qualifiedName, String.format("col%s.TABLE1.default@cl1", index));
+        attributes.put("name", "col" + index);
+
+        entity.setAttributes(attributes);
+        return entity;
+    }
+
+    private AtlasEntityWithExtInfo getAtlasEntityWithExtInfo() {
+        AtlasEntityWithExtInfo ret = new AtlasEntityWithExtInfo(getHiveTableAtlasEntity());
+
+        Map<String, AtlasEntity> referredEntities = new HashMap<>();
+        referredEntities.put("0", getHiveColumnAtlasEntity(1));
+        referredEntities.put("1", getHiveColumnAtlasEntity(2));
+        referredEntities.put("2", getHiveColumnAtlasEntity(3));
+
+        ret.setReferredEntities(referredEntities);
+
+        return ret;
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/TypeAttributeDifferenceTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/TypeAttributeDifferenceTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/TypeAttributeDifferenceTest.java
new file mode 100644
index 0000000..87cb1d4
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/TypeAttributeDifferenceTest.java
@@ -0,0 +1,150 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.impexp;
+
+import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
+import org.apache.atlas.model.typedef.AtlasEntityDef;
+import org.apache.atlas.model.typedef.AtlasEnumDef;
+import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TypeAttributeDifferenceTest {
+    private TypeAttributeDifference typeAttributeDifference;
+
+    @BeforeClass
+    public void setup() {
+        typeAttributeDifference = new TypeAttributeDifference(null, null);
+    }
+
+    private List<AtlasEnumDef.AtlasEnumElementDef> getEnumElementDefs(int startIndex, String... names) {
+        int i = startIndex;
+        List<AtlasEnumDef.AtlasEnumElementDef> list = new ArrayList<>();
+        for (String s: names) {
+            list.add(new AtlasEnumDef.AtlasEnumElementDef(s, s, i++));
+        }
+
+        return list;
+    }
+
+    private List<AtlasStructDef.AtlasAttributeDef> getAtlasAttributeDefs(String... names) {
+        List<AtlasStructDef.AtlasAttributeDef> list = new ArrayList<>();
+        for (String s : names) {
+            list.add(new AtlasStructDef.AtlasAttributeDef(s, AtlasBaseTypeDef.ATLAS_TYPE_STRING));
+        }
+
+        return list;
+    }
+
+    private AtlasEntityDef getAtlasEntityDefWithAttributes(String... attributeNames) {
+        AtlasEntityDef e = new AtlasEntityDef();
+        for (AtlasStructDef.AtlasAttributeDef a : getAtlasAttributeDefs(attributeNames)) {
+            e.addAttribute(a);
+        }
+
+        return e;
+    }
+
+    @Test
+    public void entityDefWithNoAttributes() throws Exception {
+        AtlasEntityDef existing = new AtlasEntityDef();
+        AtlasEntityDef incoming = new AtlasEntityDef();
+        List<AtlasStructDef.AtlasAttributeDef> expectedAttributes = new ArrayList<>();
+        List<AtlasStructDef.AtlasAttributeDef> actualAttributes = invokeGetAttributesAbsentInExisting(existing, incoming);
+
+        Assert.assertEquals(actualAttributes, expectedAttributes);
+    }
+
+    private List<AtlasStructDef.AtlasAttributeDef> invokeGetAttributesAbsentInExisting(AtlasStructDef existing, AtlasStructDef incoming) throws Exception {
+        return typeAttributeDifference.getElementsAbsentInExisting(existing, incoming);
+    }
+
+    private List<AtlasEnumDef.AtlasEnumElementDef> invokeGetAttributesAbsentInExisting(AtlasEnumDef existing, AtlasEnumDef incoming) throws Exception {
+        return typeAttributeDifference.getElementsAbsentInExisting(existing, incoming);
+    }
+
+    private AtlasEnumDef getAtlasEnumWithAttributes(String... elements) {
+        AtlasEnumDef enumDef = new AtlasEnumDef();
+        for (AtlasEnumDef.AtlasEnumElementDef ed : getEnumElementDefs(0, elements)) {
+            enumDef.addElement(ed);
+        }
+
+        return enumDef;
+    }
+
+    @Test
+    public void bothSame_DifferenceIsEmptyList() throws Exception {
+        AtlasEntityDef existing = getAtlasEntityDefWithAttributes("name", "qualifiedName");
+        AtlasEntityDef incoming = getAtlasEntityDefWithAttributes("name", "qualifiedName");
+
+        List<AtlasStructDef.AtlasAttributeDef> expectedAttributes = getAtlasAttributeDefs();
+        List<AtlasStructDef.AtlasAttributeDef> actualAttributes = invokeGetAttributesAbsentInExisting(existing, incoming);
+
+        Assert.assertEquals(actualAttributes, expectedAttributes);
+    }
+
+    @Test
+    public void different_ReturnsDifference() throws Exception {
+        AtlasEntityDef existing = getAtlasEntityDefWithAttributes("name");
+        AtlasEntityDef incoming = getAtlasEntityDefWithAttributes("name", "qualifiedName");
+        List<AtlasStructDef.AtlasAttributeDef> expectedAttributes = getAtlasAttributeDefs( "qualifiedName");
+
+        List<AtlasStructDef.AtlasAttributeDef> actualAttributes = invokeGetAttributesAbsentInExisting(existing, incoming);
+        Assert.assertEquals(actualAttributes, expectedAttributes);
+    }
+
+    @Test
+    public void differentSubset_ReturnsDifference() throws Exception {
+        AtlasEntityDef existing = getAtlasEntityDefWithAttributes("name", "qualifiedName");
+        AtlasEntityDef incoming = getAtlasEntityDefWithAttributes("name");
+        List<AtlasStructDef.AtlasAttributeDef> actualAttributes = invokeGetAttributesAbsentInExisting(existing, incoming);
+
+        List<AtlasStructDef.AtlasAttributeDef> expectedAttributes = getAtlasAttributeDefs();
+        Assert.assertEquals(actualAttributes, expectedAttributes);
+    }
+
+    @Test
+    public void differentEnumDef_ReturnsDifference () throws Exception {
+        AtlasEnumDef existing = getAtlasEnumWithAttributes("Alpha", "Bravo");
+        AtlasEnumDef incoming = getAtlasEnumWithAttributes("Alpha", "Bravo", "Delta", "Echo");
+        List<AtlasEnumDef.AtlasEnumElementDef> actualAttributes = invokeGetAttributesAbsentInExisting(existing, incoming);
+
+        List<AtlasEnumDef.AtlasEnumElementDef> expectedAttributes = getEnumElementDefs(2, "Delta", "Echo");
+        Assert.assertEquals(actualAttributes, expectedAttributes);
+    }
+
+    @Test
+    public void differentEnumDefs_ReturnsDifference () throws Exception {
+        AtlasEnumDef existing = getAtlasEnumWithAttributes("Alpha", "Bravo");
+        AtlasEnumDef incoming = getAtlasEnumWithAttributes("Alpha", "Bravo", "Delta", "Echo");
+        boolean ret = invokeUpdate(existing, incoming);
+
+        List<AtlasEnumDef.AtlasEnumElementDef> expectedAttributes = getEnumElementDefs(0, "Alpha", "Bravo", "Delta", "Echo");
+
+        Assert.assertTrue(ret, "Update took place");
+        Assert.assertEquals(existing.getElementDefs(), expectedAttributes);
+    }
+
+    private boolean invokeUpdate(AtlasEnumDef existing, AtlasEnumDef incoming) throws Exception {
+        return typeAttributeDifference.addElements(existing, incoming);
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/UniqueListTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/UniqueListTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/UniqueListTest.java
new file mode 100644
index 0000000..93aa518
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/UniqueListTest.java
@@ -0,0 +1,69 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.impexp;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+public class UniqueListTest {
+    private final String firstElement = "firstElement";
+    private ExportService.UniqueList<String> uniqueList;
+
+    @BeforeClass
+    public void setup() {
+        uniqueList = new ExportService.UniqueList();
+        uniqueList.add(firstElement);
+        uniqueList.add("def");
+        uniqueList.add("firstElement");
+        uniqueList.add("ghi");
+    }
+
+    @Test
+    public void add3Elements_ListHas2() {
+        assertEquals(3, uniqueList.size());
+    }
+
+    @Test
+    public void addAllList_ListHas2() {
+        ExportService.UniqueList<String> uniqueList2 = new ExportService.UniqueList<>();
+        uniqueList2.addAll(uniqueList);
+
+        assertEquals(3, uniqueList2.size());
+    }
+
+    @Test
+    public void attemptClear_SizeIsZero() {
+        ExportService.UniqueList<String> uniqueList2 = new ExportService.UniqueList<>();
+        uniqueList2.addAll(uniqueList);
+        uniqueList2.clear();
+
+        assertEquals(0, uniqueList2.size());
+    }
+
+    @Test
+    public void attemptOneRemove_SizeIsReduced() {
+        ExportService.UniqueList<String> uniqueList2 = new ExportService.UniqueList<>();
+        uniqueList2.addAll(uniqueList);
+        String removedElement = uniqueList2.remove(0);
+
+        assertEquals(2, uniqueList2.size());
+        assertEquals(firstElement, removedElement);
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java
new file mode 100644
index 0000000..5ab8c01
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java
@@ -0,0 +1,220 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.impexp;
+
+import com.google.common.collect.Sets;
+import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.TestUtilsV2;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.impexp.AtlasExportResult;
+import org.apache.atlas.model.impexp.AtlasImportRequest;
+import org.apache.atlas.model.impexp.AtlasImportResult;
+import org.apache.atlas.model.typedef.AtlasTypesDef;
+import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
+import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.atlas.utils.TestResourceFileUtils;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+public class ZipFileResourceTestUtils {
+    public static final Logger LOG = LoggerFactory.getLogger(ZipFileResourceTestUtils.class);
+
+    public static FileInputStream getFileInputStream(String fileName) {
+        return TestResourceFileUtils.getFileInputStream(fileName);
+    }
+
+    public static String getModelJson(String fileName) throws IOException {
+        String  ret                 = null;
+        File   topModelsDir         = new File(System.getProperty("user.dir") + "/../addons/models");
+        File[] topModelsDirContents = topModelsDir.exists() ? topModelsDir.listFiles() : null;
+
+        assertTrue(topModelsDirContents != null, topModelsDir.getAbsolutePath() + ": unable to find/read directory");
+        if(topModelsDirContents != null) {
+            Arrays.sort(topModelsDirContents);
+            for (File modelDir : topModelsDirContents) {
+                if (modelDir.exists() && modelDir.isDirectory()) {
+                    ret = getFileContents(modelDir, fileName);
+
+                    if (ret != null) {
+                        break;
+                    }
+                }
+            }
+
+            if (ret == null) {
+                ret = getFileContents(topModelsDir, fileName);
+            }
+
+            assertTrue(ret != null, fileName + ": unable to find model file");
+        } else {
+            throw new IOException("Unable to retrieve model contents.");
+        }
+
+        return ret;
+    }
+
+    public static String getFileContents(File dir, String fileName) throws IOException {
+        if (dir.exists() && dir.isDirectory()) {
+            File file = new File(dir, fileName);
+
+            if (file.exists() && file.isFile()) {
+                return FileUtils.readFileToString(file);
+            }
+        }
+
+        return null;
+    }
+
+    public static String getModelJsonFromResources(String fileName) throws IOException {
+        String filePath = TestResourceFileUtils.getTestFilePath(fileName);
+        File f = new File(filePath);
+        String s = FileUtils.readFileToString(f);
+        assertFalse(StringUtils.isEmpty(s), "Model file read correctly from resources!");
+
+        return s;
+    }
+
+    public static Object[][] getZipSource(String fileName) throws IOException {
+        FileInputStream fs = ZipFileResourceTestUtils.getFileInputStream(fileName);
+
+        return new Object[][]{{new ZipSource(fs)}};
+    }
+
+
+    public static void verifyImportedEntities(List<String> creationOrder, List<String> processedEntities) {
+        Set<String> lhs = com.google.common.collect.Sets.newHashSet(creationOrder);
+        Set<String> rhs = com.google.common.collect.Sets.newHashSet(processedEntities);
+        Set<String> difference = Sets.difference(lhs, rhs);
+
+        assertNotNull(difference);
+        assertEquals(difference.size(), 0);
+    }
+
+    public static void verifyImportedMetrics(AtlasExportResult exportResult, AtlasImportResult importResult) {
+        Map<String, Integer> metricsForCompare = getImportMetricsForCompare(importResult);
+        for (Map.Entry<String, Integer> entry : exportResult.getMetrics().entrySet()) {
+            if(entry.getKey().startsWith("entity") == false ||
+                    entry.getKey().contains("withExtInfo") ||
+                    entry.getKey().contains("Column") ||
+                    entry.getKey().contains("StorageDesc")) continue;
+
+            assertTrue(metricsForCompare.containsKey(entry.getKey()), entry.getKey());
+            assertEquals(entry.getValue(), metricsForCompare.get(entry.getKey()), entry.getKey());
+        }
+    }
+
+    private static Map<String,Integer> getImportMetricsForCompare(AtlasImportResult result) {
+        Map<String, Integer> r = new HashMap<>();
+        for (Map.Entry<String, Integer> entry : result.getMetrics().entrySet()) {
+            r.put(entry.getKey().replace(":updated", "").replace(":created", ""), entry.getValue());
+        }
+
+        return r;
+    }
+
+
+    public static void loadModelFromJson(String fileName, AtlasTypeDefStore typeDefStore, AtlasTypeRegistry typeRegistry) throws IOException, AtlasBaseException {
+        AtlasTypesDef typesFromJson = getAtlasTypesDefFromFile(fileName);
+        createTypesAsNeeded(typesFromJson, typeDefStore, typeRegistry);
+    }
+
+    public static void loadModelFromResourcesJson(String fileName, AtlasTypeDefStore typeDefStore, AtlasTypeRegistry typeRegistry) throws IOException, AtlasBaseException {
+        AtlasTypesDef typesFromJson = getAtlasTypesDefFromResourceFile(fileName);
+        createTypesAsNeeded(typesFromJson, typeDefStore, typeRegistry);
+    }
+
+    private static void createTypesAsNeeded(AtlasTypesDef typesFromJson, AtlasTypeDefStore typeDefStore, AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
+        if(typesFromJson == null) {
+            return;
+        }
+
+        AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(typesFromJson, typeRegistry);
+        if (typesToCreate != null && !typesToCreate.isEmpty()) {
+            typeDefStore.createTypesDef(typesToCreate);
+        }
+    }
+
+    private static AtlasTypesDef getAtlasTypesDefFromFile(String fileName) throws IOException {
+        String sampleTypes = ZipFileResourceTestUtils.getModelJson(fileName);
+        if(sampleTypes == null) return null;
+        return AtlasType.fromJson(sampleTypes, AtlasTypesDef.class);
+    }
+
+    private static AtlasTypesDef getAtlasTypesDefFromResourceFile(String fileName) throws IOException {
+        String sampleTypes = getModelJsonFromResources(fileName);
+        return AtlasType.fromJson(sampleTypes, AtlasTypesDef.class);
+    }
+
+    public static AtlasImportRequest getDefaultImportRequest() {
+        return new AtlasImportRequest();
+    }
+
+
+    public static AtlasImportResult runImportWithParameters(ImportService importService, AtlasImportRequest request, ZipSource source) throws AtlasBaseException, IOException {
+        final String requestingIP = "1.0.0.0";
+        final String hostName = "localhost";
+        final String userName = "admin";
+
+        AtlasImportResult result = importService.run(source, request, userName, hostName, requestingIP);
+        assertEquals(result.getOperationStatus(), AtlasImportResult.OperationStatus.SUCCESS);
+        return result;
+    }
+
+    public static AtlasImportResult runImportWithNoParameters(ImportService importService, ZipSource source) throws AtlasBaseException, IOException {
+        final String requestingIP = "1.0.0.0";
+        final String hostName = "localhost";
+        final String userName = "admin";
+
+        AtlasImportResult result = importService.run(source, userName, hostName, requestingIP);
+        assertEquals(result.getOperationStatus(), AtlasImportResult.OperationStatus.SUCCESS);
+        return result;
+    }
+
+    public static void runAndVerifyQuickStart_v1_Import(ImportService importService, ZipSource zipSource) throws AtlasBaseException, IOException {
+        AtlasExportResult exportResult = zipSource.getExportResult();
+        List<String> creationOrder = zipSource.getCreationOrder();
+
+        RequestContextV1.clear();
+        RequestContextV1.get().setUser(TestUtilsV2.TEST_USER);
+
+        AtlasImportRequest request = getDefaultImportRequest();
+        AtlasImportResult result = runImportWithParameters(importService, request, zipSource);
+
+        assertNotNull(result);
+        verifyImportedMetrics(exportResult, result);
+        verifyImportedEntities(creationOrder, result.getProcessedEntities());
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/impexp/ZipSinkTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ZipSinkTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ZipSinkTest.java
new file mode 100644
index 0000000..e8bbeb5
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ZipSinkTest.java
@@ -0,0 +1,210 @@
+/**
+ * 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.impexp;
+
+
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.impexp.AtlasExportRequest;
+import org.apache.atlas.model.impexp.AtlasExportResult;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.type.AtlasType;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import static org.testng.Assert.*;
+
+public class ZipSinkTest {
+    private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+    private ZipSink zipSink;
+    private List<String> defaultExportOrder = new ArrayList<>(Arrays.asList("a", "b", "c", "d"));
+    private AtlasExportResult defaultExportResult;
+    private String knownEntityGuidFormat = "111-222-333-%s";
+
+
+    private void initZipSinkWithExportOrder() throws AtlasBaseException {
+        zipSink = new ZipSink(byteArrayOutputStream);
+        zipSink.setExportOrder(defaultExportOrder);
+        zipSink.close();
+    }
+
+    private AtlasExportResult getDefaultExportResult() {
+        AtlasExportRequest request = new AtlasExportRequest();
+
+        List<AtlasObjectId> itemsToExport = new ArrayList<>();
+        itemsToExport.add(new AtlasObjectId("hive_db", "qualifiedName", "default"));
+        request.setItemsToExport(itemsToExport);
+
+        defaultExportResult = new AtlasExportResult(request, "admin", "1.0.0.0", "root", 100);
+        return defaultExportResult;
+    }
+
+    private ZipInputStream getZipInputStreamForDefaultExportOrder() throws AtlasBaseException {
+        initZipSinkWithExportOrder();
+
+        ByteArrayInputStream bis = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
+        return new ZipInputStream(bis);
+    }
+
+    private String getZipEntryAsStream(ZipInputStream zis) throws IOException {
+        byte[] buf = new byte[1024];
+        int n = 0;
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        while ((n = zis.read(buf, 0, 1024)) > -1) {
+            bos.write(buf, 0, n);
+        }
+
+        Assert.assertNotNull(bos);
+        return bos.toString();
+    }
+
+    @Test
+    public void correctInit_succeeds() throws AtlasBaseException {
+        initZipSinkWithExportOrder();
+        assertTrue(true);
+        Assert.assertNotNull(zipSink);
+    }
+
+    @Test
+    public void zipWithExactlyOneEntry_succeeds() {
+
+        try {
+            ZipInputStream zis = getZipInputStreamForDefaultExportOrder();
+
+            try {
+                Assert.assertNotNull(zis.getNextEntry());
+                Assert.assertNull(zis.getNextEntry());
+            } catch (IOException e) {
+
+                assertTrue(false);
+            }
+        } catch (AtlasBaseException e) {
+
+            assertTrue(false, "No exception should be thrown.");
+        }
+    }
+
+    @Test
+    public void verifyExportOrderEntryName_verifies() throws AtlasBaseException, IOException {
+
+        ZipInputStream zis = getZipInputStreamForDefaultExportOrder();
+        ZipEntry ze = zis.getNextEntry();
+
+        assertEquals(ze.getName().replace(".json", ""), ZipExportFileNames.ATLAS_EXPORT_ORDER_NAME.toString());
+    }
+
+    @Test
+    public void zipWithExactlyOneEntry_ContentsVerified() throws AtlasBaseException, IOException {
+
+        ZipInputStream zis = getZipInputStreamForDefaultExportOrder();
+        zis.getNextEntry();
+
+        assertEquals(getZipEntryAsStream(zis).replace("\"", "'"), "['a','b','c','d']");
+    }
+
+    @Test
+    public void zipWithExactlyTwoEntries_ContentsVerified() throws AtlasBaseException, IOException {
+
+        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
+        useZipSinkToCreateEntries(byteOutputStream);
+
+        ByteArrayInputStream bis = new ByteArrayInputStream(byteOutputStream.toByteArray());
+        ZipInputStream zipStream = new ZipInputStream(bis);
+        ZipEntry entry = zipStream.getNextEntry();
+
+        assertEquals(getZipEntryAsStream(zipStream), "[\"a\",\"b\",\"c\",\"d\"]");
+        assertEquals(entry.getName().replace(".json", ""), ZipExportFileNames.ATLAS_EXPORT_ORDER_NAME.toString());
+
+        entry = zipStream.getNextEntry();
+        assertEquals(entry.getName().replace(".json", ""), ZipExportFileNames.ATLAS_EXPORT_INFO_NAME.toString());
+        assertTrue(compareJsonWithObject(getZipEntryAsStream(zipStream), defaultExportResult));
+    }
+
+    @Test
+    public void recordsEntityEntries() throws AtlasBaseException {
+        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
+        ZipSink zs = new ZipSink(byteOutputStream);
+
+        AtlasEntity entity = new AtlasEntity();
+        entity.setGuid(String.format(knownEntityGuidFormat, 0));
+
+        zs.add(entity);
+        assertTrue(zs.hasEntity(String.format(knownEntityGuidFormat, 0)));
+
+        zs.close();
+    }
+
+    @Test
+    public void recordsEntityWithExtInfoEntries() throws AtlasBaseException {
+        final int max_entries = 3;
+        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
+        ZipSink zs = new ZipSink(byteOutputStream);
+
+        AtlasEntity entity = new AtlasEntity();
+        entity.setGuid(String.format(knownEntityGuidFormat, 0));
+
+        AtlasEntity.AtlasEntityWithExtInfo entityWithExtInfo = new AtlasEntity.AtlasEntityWithExtInfo(entity);
+        addReferredEntities(entityWithExtInfo, max_entries);
+
+        zs.add(entityWithExtInfo);
+        for (int i = 0; i <= max_entries; i++) {
+            String g = String.format(knownEntityGuidFormat, i);
+            assertTrue(zs.hasEntity(g));
+        }
+
+        zs.close();
+    }
+
+    private void addReferredEntities(AtlasEntity.AtlasEntityWithExtInfo entityWithExtInfo, int maxEntries) {
+
+        for (int i = 1; i <= maxEntries; i++) {
+            AtlasEntity entity1 = new AtlasEntity();
+            entity1.setGuid(String.format(knownEntityGuidFormat, i));
+            entityWithExtInfo.addReferredEntity(entity1);
+        }
+    }
+
+    @Test
+    public void recordsDoesNotRecordEntityEntries() throws AtlasBaseException {
+        initZipSinkWithExportOrder();
+
+        assertNotNull(zipSink);
+        assertFalse(zipSink.hasEntity(ZipExportFileNames.ATLAS_EXPORT_ORDER_NAME.toString()));
+    }
+
+    private void useZipSinkToCreateEntries(ByteArrayOutputStream byteOutputStream) throws AtlasBaseException {
+        ZipSink zs = new ZipSink(byteOutputStream);
+        zs.setExportOrder(defaultExportOrder);
+        zs.setResult(getDefaultExportResult());
+        zs.close();
+    }
+
+    private boolean compareJsonWithObject(String s, AtlasExportResult defaultExportResult) {
+        String json = AtlasType.toJson(defaultExportResult);
+        return json.equals(s);
+    }
+}


[2/5] atlas git commit: ATLAS-2251: restored bunch of deleted tests

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java
new file mode 100644
index 0000000..d207a69
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java
@@ -0,0 +1,623 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.store.graph.v1;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.TestUtilsV2;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
+import org.apache.atlas.model.instance.AtlasEntityHeader;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.model.instance.AtlasRelatedObjectId;
+import org.apache.atlas.model.instance.EntityMutationResponse;
+import org.apache.atlas.model.typedef.AtlasTypesDef;
+import org.apache.atlas.repository.graph.AtlasGraphProvider;
+import org.apache.atlas.repository.graph.GraphBackedSearchIndexer;
+import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
+import org.apache.atlas.repository.store.graph.AtlasEntityStore;
+import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
+import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasEntityType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.commons.collections.CollectionUtils;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.atlas.TestRelationshipUtilsV2.EMPLOYEE_TYPE;
+import static org.apache.atlas.TestRelationshipUtilsV2.getDepartmentEmployeeInstances;
+import static org.apache.atlas.TestRelationshipUtilsV2.getDepartmentEmployeeTypes;
+import static org.apache.atlas.TestRelationshipUtilsV2.getInverseReferenceTestTypes;
+import static org.apache.atlas.TestUtilsV2.NAME;
+import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
+import static org.mockito.Mockito.mock;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+@Guice(modules = TestModules.TestOnlyModule.class)
+public abstract class AtlasRelationshipStoreV1Test {
+
+    @Inject
+    AtlasTypeRegistry typeRegistry;
+
+    @Inject
+    AtlasTypeDefStore typeDefStore;
+
+    @Inject
+    DeleteHandlerV1   deleteHandler;
+
+    @Inject
+    EntityGraphMapper graphMapper;
+
+    AtlasEntityStore          entityStore;
+    AtlasRelationshipStore    relationshipStore;
+    AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class);
+
+    protected Map<String, AtlasObjectId> employeeNameIdMap = new HashMap<>();
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        new GraphBackedSearchIndexer(typeRegistry);
+
+        // create employee relationship types
+        AtlasTypesDef employeeTypes = getDepartmentEmployeeTypes();
+        typeDefStore.createTypesDef(employeeTypes);
+
+        AtlasEntitiesWithExtInfo employeeInstances = getDepartmentEmployeeInstances();
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(employeeInstances), false);
+
+        for (AtlasEntityHeader entityHeader : response.getCreatedEntities()) {
+            employeeNameIdMap.put((String) entityHeader.getAttribute(NAME), getAtlasObjectId(entityHeader));
+        }
+
+        init();
+        AtlasTypesDef typesDef = getInverseReferenceTestTypes();
+
+        AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(typesDef, typeRegistry);
+
+        if (!typesToCreate.isEmpty()) {
+            typeDefStore.createTypesDef(typesToCreate);
+        }
+    }
+
+    @BeforeTest
+    public void init() throws Exception {
+        entityStore       = new AtlasEntityStoreV1(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper);
+        relationshipStore = new AtlasRelationshipStoreV1(typeRegistry);
+
+        RequestContextV1.clear();
+        RequestContextV1.get().setUser(TestUtilsV2.TEST_USER);
+    }
+
+    @AfterClass
+    public void clear() {
+        AtlasGraphProvider.cleanup();
+    }
+
+    @Test
+    public void testDepartmentEmployeeEntitiesUsingRelationship() throws Exception  {
+        AtlasObjectId hrId     = employeeNameIdMap.get("hr");
+        AtlasObjectId maxId    = employeeNameIdMap.get("Max");
+        AtlasObjectId johnId   = employeeNameIdMap.get("John");
+        AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+        AtlasObjectId janeId   = employeeNameIdMap.get("Jane");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
+
+        AtlasEntity hrDept = getEntityFromStore(hrId.getGuid());
+        AtlasEntity max    = getEntityFromStore(maxId.getGuid());
+        AtlasEntity john   = getEntityFromStore(johnId.getGuid());
+        AtlasEntity julius = getEntityFromStore(juliusId.getGuid());
+        AtlasEntity jane   = getEntityFromStore(janeId.getGuid());
+        AtlasEntity mike   = getEntityFromStore(mikeId.getGuid());
+
+        // Department relationship attributes
+        List<AtlasObjectId> deptEmployees = toAtlasObjectIds(hrDept.getRelationshipAttribute("employees"));
+        assertNotNull(deptEmployees);
+        assertEquals(deptEmployees.size(), 5);
+        assertObjectIdsContains(deptEmployees, maxId);
+        assertObjectIdsContains(deptEmployees, johnId);
+        assertObjectIdsContains(deptEmployees, juliusId);
+        assertObjectIdsContains(deptEmployees, janeId);
+        assertObjectIdsContains(deptEmployees, mikeId);
+
+        // Max employee validation
+        AtlasObjectId maxDepartmentId = toAtlasObjectId(max.getRelationshipAttribute("department"));
+        assertNotNull(maxDepartmentId);
+        assertObjectIdEquals(maxDepartmentId, hrId);
+
+        AtlasObjectId maxManagerId = toAtlasObjectId(max.getRelationshipAttribute("manager"));
+        assertNotNull(maxManagerId);
+        assertObjectIdEquals(maxManagerId, janeId);
+
+        List<AtlasObjectId> maxMentorsId = toAtlasObjectIds(max.getRelationshipAttribute("mentors"));
+        assertNotNull(maxMentorsId);
+        assertEquals(maxMentorsId.size(), 1);
+        assertObjectIdEquals(maxMentorsId.get(0), juliusId);
+
+        List<AtlasObjectId> maxMenteesId = toAtlasObjectIds(max.getRelationshipAttribute("mentees"));
+        assertNotNull(maxMenteesId);
+        assertEquals(maxMenteesId.size(), 1);
+        assertObjectIdEquals(maxMenteesId.get(0), johnId);
+
+        List<AtlasObjectId> maxFriendsIds = toAtlasObjectIds(max.getRelationshipAttribute("friends"));
+        assertNotNull(maxFriendsIds);
+        assertEquals(maxFriendsIds.size(), 2);
+        assertObjectIdsContains(maxFriendsIds, mikeId);
+        assertObjectIdsContains(maxFriendsIds, johnId);
+
+        // John Employee validation
+        AtlasObjectId johnDepartmentId = toAtlasObjectId(john.getRelationshipAttribute("department"));
+        assertNotNull(johnDepartmentId);
+        assertObjectIdEquals(johnDepartmentId, hrId);
+
+        AtlasObjectId johnManagerId = toAtlasObjectId(john.getRelationshipAttribute("manager"));
+        assertNotNull(johnManagerId);
+        assertObjectIdEquals(johnManagerId, janeId);
+
+        List<AtlasObjectId> johnMentorIds = toAtlasObjectIds(john.getRelationshipAttribute("mentors"));
+        assertNotNull(johnMentorIds);
+        assertEquals(johnMentorIds.size(), 2);
+        assertObjectIdsContains(johnMentorIds, maxId);
+        assertObjectIdsContains(johnMentorIds, juliusId);
+
+        List<AtlasObjectId> johnMenteesId = toAtlasObjectIds(john.getRelationshipAttribute("mentees"));
+        assertEmpty(johnMenteesId);
+
+        List<AtlasObjectId> johnFriendsIds = toAtlasObjectIds(john.getRelationshipAttribute("friends"));
+        assertNotNull(johnFriendsIds);
+        assertEquals(johnFriendsIds.size(), 2);
+        assertObjectIdsContains(johnFriendsIds, mikeId);
+        assertObjectIdsContains(johnFriendsIds, maxId);
+
+        // Mike Employee validation
+        AtlasObjectId mikeDepartmentId = toAtlasObjectId(mike.getRelationshipAttribute("department"));
+        assertNotNull(mikeDepartmentId);
+        assertObjectIdEquals(mikeDepartmentId, hrId);
+
+        AtlasObjectId mikeManagerId = toAtlasObjectId(mike.getRelationshipAttribute("manager"));
+        assertNotNull(mikeManagerId);
+        assertObjectIdEquals(mikeManagerId, juliusId);
+
+        List<AtlasObjectId> mikeMentorIds = toAtlasObjectIds(mike.getRelationshipAttribute("mentors"));
+        assertEmpty(mikeMentorIds);
+
+        List<AtlasObjectId> mikeMenteesId = toAtlasObjectIds(mike.getRelationshipAttribute("mentees"));
+        assertEmpty(mikeMenteesId);
+
+        List<AtlasObjectId> mikeFriendsIds = toAtlasObjectIds(mike.getRelationshipAttribute("friends"));
+        assertNotNull(mikeFriendsIds);
+        assertEquals(mikeFriendsIds.size(), 2);
+        assertObjectIdsContains(mikeFriendsIds, maxId);
+        assertObjectIdsContains(mikeFriendsIds, johnId);
+
+        // Jane Manager validation
+        AtlasObjectId janeDepartmentId = toAtlasObjectId(jane.getRelationshipAttribute("department"));
+        assertNotNull(janeDepartmentId);
+        assertObjectIdEquals(janeDepartmentId, hrId);
+
+        AtlasObjectId janeManagerId = toAtlasObjectId(jane.getRelationshipAttribute("manager"));
+        assertNull(janeManagerId);
+
+        List<AtlasObjectId> janeMentorIds = toAtlasObjectIds(jane.getRelationshipAttribute("mentors"));
+        assertEmpty(janeMentorIds);
+
+        List<AtlasObjectId> janeMenteesId = toAtlasObjectIds(jane.getRelationshipAttribute("mentees"));
+        assertEmpty(janeMenteesId);
+
+        List<AtlasObjectId> janeSubordinateIds = toAtlasObjectIds(jane.getRelationshipAttribute("subordinates"));
+        assertNotNull(janeSubordinateIds);
+        assertEquals(janeSubordinateIds.size(), 2);
+        assertObjectIdsContains(janeSubordinateIds, maxId);
+        assertObjectIdsContains(janeSubordinateIds, johnId);
+
+        List<AtlasObjectId> janeFriendsIds = toAtlasObjectIds(jane.getRelationshipAttribute("friends"));
+        assertEmpty(janeFriendsIds);
+
+        AtlasObjectId janeSiblingId = toAtlasObjectId(jane.getRelationshipAttribute("sibling"));
+        assertNotNull(janeSiblingId);
+        assertObjectIdEquals(janeSiblingId, juliusId);
+
+        // Julius Manager validation
+        AtlasObjectId juliusDepartmentId = toAtlasObjectId(julius.getRelationshipAttribute("department"));
+        assertNotNull(juliusDepartmentId);
+        assertObjectIdEquals(juliusDepartmentId, hrId);
+
+        AtlasObjectId juliusManagerId = toAtlasObjectId(julius.getRelationshipAttribute("manager"));
+        assertNull(juliusManagerId);
+
+        List<AtlasObjectId> juliusMentorIds = toAtlasObjectIds(julius.getRelationshipAttribute("mentors"));
+        assertEmpty(juliusMentorIds);
+
+        List<AtlasObjectId> juliusMenteesId = toAtlasObjectIds(julius.getRelationshipAttribute("mentees"));
+        assertNotNull(juliusMenteesId);
+        assertEquals(juliusMenteesId.size(), 2);
+        assertObjectIdsContains(juliusMenteesId, maxId);
+        assertObjectIdsContains(juliusMenteesId, johnId);
+
+        List<AtlasObjectId> juliusSubordinateIds = toAtlasObjectIds(julius.getRelationshipAttribute("subordinates"));
+        assertNotNull(juliusSubordinateIds);
+        assertEquals(juliusSubordinateIds.size(), 1);
+        assertObjectIdsContains(juliusSubordinateIds, mikeId);
+
+        List<AtlasObjectId> juliusFriendsIds = toAtlasObjectIds(julius.getRelationshipAttribute("friends"));
+        assertEmpty(juliusFriendsIds);
+
+        AtlasObjectId juliusSiblingId = toAtlasObjectId(julius.getRelationshipAttribute("sibling"));
+        assertNotNull(juliusSiblingId);
+        assertObjectIdEquals(juliusSiblingId, janeId);
+    }
+
+    // Seeing intermittent failures with janus profile, disabling it until its fixed.
+    @Test(enabled = false)
+    public void testRelationshipAttributeUpdate_NonComposite_OneToMany() throws Exception {
+        AtlasObjectId maxId    = employeeNameIdMap.get("Max");
+        AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+        AtlasObjectId janeId   = employeeNameIdMap.get("Jane");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
+        AtlasObjectId johnId   = employeeNameIdMap.get("John");
+
+        // Change Max's Employee.manager reference to Julius and apply the change as a partial update.
+        // This should also update Julius to add Max to the inverse Manager.subordinates reference.
+        AtlasEntity maxEntityForUpdate = new AtlasEntity(EMPLOYEE_TYPE);
+        maxEntityForUpdate.setRelationshipAttribute("manager", juliusId);
+
+        AtlasEntityType        employeeType   = typeRegistry.getEntityTypeByName(EMPLOYEE_TYPE);
+        Map<String, Object>    uniqAttributes = Collections.<String, Object>singletonMap("name", "Max");
+        EntityMutationResponse updateResponse = entityStore.updateByUniqueAttributes(employeeType, uniqAttributes , new AtlasEntityWithExtInfo(maxEntityForUpdate));
+
+        List<AtlasEntityHeader> partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
+        assertEquals(partialUpdatedEntities.size(), 3);
+        // 3 entities should have been updated:
+        // * Max to change the Employee.manager reference
+        // * Julius to add Max to Manager.subordinates
+        // * Jane to remove Max from Manager.subordinates
+
+        AtlasEntitiesWithExtInfo updatedEntities = entityStore.getByIds(ImmutableList.of(maxId.getGuid(), juliusId.getGuid(), janeId.getGuid()));
+
+        // Max's manager updated as Julius
+        AtlasEntity maxEntity = updatedEntities.getEntity(maxId.getGuid());
+        verifyRelationshipAttributeValue(maxEntity, "manager", juliusId.getGuid());
+
+        // Max added to the subordinate list of Julius, existing subordinate is Mike
+        AtlasEntity juliusEntity = updatedEntities.getEntity(juliusId.getGuid());
+        verifyRelationshipAttributeList(juliusEntity, "subordinates", ImmutableList.of(maxId, mikeId));
+
+        // Max removed from the subordinate list of Julius
+        AtlasEntity janeEntity = updatedEntities.getEntity(janeId.getGuid());
+
+        // Jane's subordinates list includes John and Max for soft delete
+        // Jane's subordinates list includes only John for hard delete
+        verifyRelationshipAttributeUpdate_NonComposite_OneToMany(janeEntity);
+
+        // Remove Mike from Max's friends list
+        // Max's current friends: [Mike, John]
+        // Max's updated friends: [Julius, John]
+        maxEntityForUpdate = new AtlasEntity(EMPLOYEE_TYPE);
+        maxEntityForUpdate.setRelationshipAttribute("friends", ImmutableList.of(johnId, juliusId));
+
+        init();
+        updateResponse = entityStore.updateByUniqueAttributes(employeeType, uniqAttributes , new AtlasEntityWithExtInfo(maxEntityForUpdate));
+
+        partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
+        assertEquals(partialUpdatedEntities.size(), 3);
+        // 3 entities should have been updated:
+        // * Max added Julius and removed Mike from Employee.friends
+        // * Mike removed Max from Employee.friends
+        // * Julius added Max in Employee.friends
+
+        updatedEntities = entityStore.getByIds(ImmutableList.of(maxId.getGuid(), mikeId.getGuid(), johnId.getGuid(), juliusId.getGuid()));
+
+        maxEntity    = updatedEntities.getEntity(maxId.getGuid());
+        juliusEntity = updatedEntities.getEntity(juliusId.getGuid());
+        AtlasEntity mikeEntity = updatedEntities.getEntity(mikeId.getGuid());
+        AtlasEntity johnEntity = updatedEntities.getEntity(johnId.getGuid());
+
+        verifyRelationshipAttributeUpdate_ManyToMany_Friends(maxEntity, juliusEntity, mikeEntity, johnEntity);
+
+        // Remove Julius from Jane's sibling and add Mike as new sibling
+        AtlasEntity juliusEntityForUpdate = new AtlasEntity(EMPLOYEE_TYPE);
+        juliusEntityForUpdate.setRelationshipAttribute("sibling", mikeId);
+
+        init();
+        updateResponse = entityStore.updateByUniqueAttributes(employeeType, Collections.<String, Object>singletonMap("name", "Julius") , new AtlasEntityWithExtInfo(juliusEntityForUpdate));
+        partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
+        assertEquals(partialUpdatedEntities.size(), 3);
+
+        updatedEntities = entityStore.getByIds(ImmutableList.of(juliusId.getGuid(), janeId.getGuid(), mikeId.getGuid()));
+
+        juliusEntity = updatedEntities.getEntity(juliusId.getGuid());
+        janeEntity   = updatedEntities.getEntity(janeId.getGuid());
+        mikeEntity   = updatedEntities.getEntity(mikeId.getGuid());
+
+        verifyRelationshipAttributeUpdate_OneToOne_Sibling(juliusEntity, janeEntity, mikeEntity);
+    }
+
+    @Test
+    public void testRelationshipAttributeUpdate_NonComposite_ManyToOne() throws Exception {
+        AtlasEntity a1 = new AtlasEntity("A");
+        a1.setAttribute(NAME, "a1_name");
+
+        AtlasEntity a2 = new AtlasEntity("A");
+        a2.setAttribute(NAME, "a2_name");
+
+        AtlasEntity a3 = new AtlasEntity("A");
+        a3.setAttribute(NAME, "a3_name");
+
+        AtlasEntity b = new AtlasEntity("B");
+        b.setAttribute(NAME, "b_name");
+
+        AtlasEntitiesWithExtInfo entitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+        entitiesWithExtInfo.addEntity(a1);
+        entitiesWithExtInfo.addEntity(a2);
+        entitiesWithExtInfo.addEntity(a3);
+        entitiesWithExtInfo.addEntity(b);
+        entityStore.createOrUpdate(new AtlasEntityStream(entitiesWithExtInfo) , false);
+
+        AtlasEntity bPartialUpdate = new AtlasEntity("B");
+        bPartialUpdate.setRelationshipAttribute("manyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+        init();
+        EntityMutationResponse response = entityStore.updateByUniqueAttributes(typeRegistry.getEntityTypeByName("B"),
+                                                                               Collections.singletonMap(NAME, b.getAttribute(NAME)),
+                                                                               new AtlasEntityWithExtInfo(bPartialUpdate));
+        // Verify 3 entities were updated:
+        // * set b.manyA reference to a1 and a2
+        // * set inverse a1.oneB reference to b
+        // * set inverse a2.oneB reference to b
+        assertEquals(response.getPartialUpdatedEntities().size(), 3);
+        AtlasEntitiesWithExtInfo updatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
+
+        AtlasEntity a1Entity = updatedEntities.getEntity(a1.getGuid());
+        verifyRelationshipAttributeValue(a1Entity, "oneB", b.getGuid());
+
+        AtlasEntity a2Entity = updatedEntities.getEntity(a2.getGuid());
+        verifyRelationshipAttributeValue(a2Entity, "oneB", b.getGuid());
+
+        AtlasEntity bEntity = updatedEntities.getEntity(b.getGuid());
+        verifyRelationshipAttributeList(bEntity, "manyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+
+        bPartialUpdate.setRelationshipAttribute("manyA", ImmutableList.of(getAtlasObjectId(a3)));
+        init();
+        response = entityStore.updateByUniqueAttributes(typeRegistry.getEntityTypeByName("B"),
+                                                        Collections.singletonMap(NAME, b.getAttribute(NAME)),
+                                                        new AtlasEntityWithExtInfo(bPartialUpdate));
+        // Verify 4 entities were updated:
+        // * set b.manyA reference to a3
+        // * set inverse a3.oneB reference to b
+        // * disconnect inverse a1.oneB reference to b
+        // * disconnect inverse a2.oneB reference to b
+        assertEquals(response.getPartialUpdatedEntities().size(), 4);
+        init();
+
+        updatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), a3.getGuid(), b.getGuid()));
+        a1Entity        = updatedEntities.getEntity(a1.getGuid());
+        a2Entity        = updatedEntities.getEntity(a2.getGuid());
+        bEntity         = updatedEntities.getEntity(b.getGuid());
+
+        AtlasEntity a3Entity = updatedEntities.getEntity(a3.getGuid());
+        verifyRelationshipAttributeValue(a3Entity, "oneB", b.getGuid());
+
+        verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(a1Entity, a2Entity, a3Entity, bEntity);
+    }
+
+    @Test
+    public void testRelationshipAttributeUpdate_NonComposite_OneToOne() throws Exception {
+        AtlasEntity a1 = new AtlasEntity("A");
+        a1.setAttribute(NAME, "a1_name");
+
+        AtlasEntity a2 = new AtlasEntity("A");
+        a2.setAttribute(NAME, "a2_name");
+
+        AtlasEntity b = new AtlasEntity("B");
+        b.setAttribute(NAME, "b_name");
+
+        AtlasEntitiesWithExtInfo entitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+        entitiesWithExtInfo.addEntity(a1);
+        entitiesWithExtInfo.addEntity(a2);
+        entitiesWithExtInfo.addEntity(b);
+
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesWithExtInfo) , false);
+
+        AtlasEntity partialUpdateB = new AtlasEntity("B");
+        partialUpdateB.setRelationshipAttribute("a", getAtlasObjectId(a1));
+
+        init();
+        AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
+
+        response = entityStore.updateByUniqueAttributes(bType, Collections.singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(partialUpdateB));
+        List<AtlasEntityHeader> partialUpdatedEntitiesHeader = response.getPartialUpdatedEntities();
+        // Verify 2 entities were updated:
+        // * set b.a reference to a1
+        // * set inverse a1.b reference to b
+        assertEquals(partialUpdatedEntitiesHeader.size(), 2);
+        AtlasEntitiesWithExtInfo partialUpdatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b.getGuid()));
+
+        AtlasEntity a1Entity = partialUpdatedEntities.getEntity(a1.getGuid());
+        verifyRelationshipAttributeValue(a1Entity, "b", b.getGuid());
+
+        AtlasEntity bEntity = partialUpdatedEntities.getEntity(b.getGuid());
+        verifyRelationshipAttributeValue(bEntity, "a", a1.getGuid());
+
+        init();
+
+        // Update b.a to reference a2.
+        partialUpdateB.setRelationshipAttribute("a", getAtlasObjectId(a2));
+        response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(partialUpdateB));
+        partialUpdatedEntitiesHeader = response.getPartialUpdatedEntities();
+        // Verify 3 entities were updated:
+        // * set b.a reference to a2
+        // * set a2.b reference to b
+        // * disconnect a1.b reference
+        assertEquals(partialUpdatedEntitiesHeader.size(), 3);
+        partialUpdatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
+
+        bEntity = partialUpdatedEntities.getEntity(b.getGuid());
+        verifyRelationshipAttributeValue(bEntity, "a", a2.getGuid());
+
+        AtlasEntity a2Entity = partialUpdatedEntities.getEntity(a2.getGuid());
+        verifyRelationshipAttributeValue(a2Entity, "b", b.getGuid());
+
+        a1Entity = partialUpdatedEntities.getEntity(a1.getGuid());
+        verifyRelationshipAttributeUpdate_NonComposite_OneToOne(a1Entity, bEntity);
+    }
+
+    @Test
+    public void testRelationshipAttributeUpdate_NonComposite_ManyToMany() throws Exception {
+        AtlasEntity a1 = new AtlasEntity("A");
+        a1.setAttribute(NAME, "a1_name");
+
+        AtlasEntity a2 = new AtlasEntity("A");
+        a2.setAttribute(NAME, "a2_name");
+
+        AtlasEntity a3 = new AtlasEntity("A");
+        a3.setAttribute(NAME, "a3_name");
+
+        AtlasEntity b1 = new AtlasEntity("B");
+        b1.setAttribute(NAME, "b1_name");
+
+        AtlasEntity b2 = new AtlasEntity("B");
+        b2.setAttribute(NAME, "b2_name");
+
+        AtlasEntitiesWithExtInfo entitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+        entitiesWithExtInfo.addEntity(a1);
+        entitiesWithExtInfo.addEntity(a2);
+        entitiesWithExtInfo.addEntity(a3);
+        entitiesWithExtInfo.addEntity(b1);
+        entitiesWithExtInfo.addEntity(b2);
+        entityStore.createOrUpdate(new AtlasEntityStream(entitiesWithExtInfo) , false);
+
+        AtlasEntity b1PartialUpdate = new AtlasEntity("B");
+        b1PartialUpdate.setRelationshipAttribute("manyToManyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+        init();
+        EntityMutationResponse response = entityStore.updateByUniqueAttributes(typeRegistry.getEntityTypeByName("B"),
+                                                                               Collections.singletonMap(NAME, b1.getAttribute(NAME)),
+                                                                               new AtlasEntityWithExtInfo(b1PartialUpdate));
+
+        List<AtlasEntityHeader> updatedEntityHeaders = response.getPartialUpdatedEntities();
+        assertEquals(updatedEntityHeaders.size(), 3);
+
+        AtlasEntitiesWithExtInfo updatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b1.getGuid()));
+
+        AtlasEntity b1Entity = updatedEntities.getEntity(b1.getGuid());
+        verifyRelationshipAttributeList(b1Entity, "manyToManyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+        AtlasEntity a1Entity = updatedEntities.getEntity(a1.getGuid());
+        verifyRelationshipAttributeList(a1Entity, "manyB", ImmutableList.of(getAtlasObjectId(b1)));
+
+        AtlasEntity a2Entity = updatedEntities.getEntity(a2.getGuid());
+        verifyRelationshipAttributeList(a2Entity, "manyB", ImmutableList.of(getAtlasObjectId(b1)));
+    }
+
+    protected abstract void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b);
+
+    protected abstract void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity entity) throws Exception;
+
+    protected abstract void verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(AtlasEntity a1, AtlasEntity a2, AtlasEntity a3, AtlasEntity b);
+
+    protected abstract void verifyRelationshipAttributeUpdate_ManyToMany_Friends(AtlasEntity e1, AtlasEntity e2, AtlasEntity e3, AtlasEntity e4) throws Exception;
+
+    protected abstract void verifyRelationshipAttributeUpdate_OneToOne_Sibling(AtlasEntity e1, AtlasEntity e2, AtlasEntity e3) throws Exception;
+
+    protected static void assertObjectIdsContains(List<AtlasObjectId> objectIds, AtlasObjectId objectId) {
+        assertTrue(CollectionUtils.isNotEmpty(objectIds));
+        assertTrue(objectIds.contains(objectId));
+    }
+
+    protected static void assertObjectIdEquals(AtlasObjectId objId1, AtlasObjectId objId2) {
+        assertTrue(objId1.equals(objId2));
+    }
+
+    private static void assertEmpty(List collection) {
+        assertTrue(collection != null && collection.isEmpty());
+    }
+
+    protected static List<AtlasObjectId> toAtlasObjectIds(Object object) {
+        List<AtlasObjectId> ret = new ArrayList<>();
+
+        if (object instanceof List) {
+            List<?> objectIds = (List) object;
+
+            if (CollectionUtils.isNotEmpty(objectIds)) {
+                for (Object obj : objectIds) {
+                    if (obj instanceof AtlasRelatedObjectId) {
+                        AtlasRelatedObjectId relatedObjectId = (AtlasRelatedObjectId) obj;
+                        ret.add(new AtlasObjectId(relatedObjectId.getGuid(), relatedObjectId.getTypeName(), relatedObjectId.getUniqueAttributes()));
+                    }
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    protected static AtlasObjectId toAtlasObjectId(Object object) {
+        if (object instanceof AtlasRelatedObjectId) {
+            AtlasRelatedObjectId relatedObjectId = (AtlasRelatedObjectId) object;
+            return new AtlasObjectId(relatedObjectId.getGuid(), relatedObjectId.getTypeName(), relatedObjectId.getUniqueAttributes());
+        }
+
+        return null;
+    }
+
+    private AtlasEntity getEntityFromStore(String guid) throws AtlasBaseException {
+        AtlasEntityWithExtInfo entity = guid != null ? entityStore.getById(guid) : null;
+
+        return entity != null ? entity.getEntity() : null;
+    }
+
+    protected static void verifyRelationshipAttributeList(AtlasEntity entity, String relationshipAttrName, List<AtlasObjectId> expectedValues) {
+        Object refValue = entity.getRelationshipAttribute(relationshipAttrName);
+        assertTrue(refValue instanceof List);
+
+        List<AtlasObjectId> refList = toAtlasObjectIds(refValue);
+        assertEquals(refList.size(), expectedValues.size());
+
+        if (expectedValues.size() > 0) {
+            assertTrue(refList.containsAll(expectedValues));
+        }
+    }
+
+    protected static void verifyRelationshipAttributeValue(AtlasEntity entity, String relationshipAttrName, String expectedGuid) {
+        Object refValue = entity.getRelationshipAttribute(relationshipAttrName);
+        if (expectedGuid == null) {
+            assertNull(refValue);
+        }
+        else {
+            assertTrue(refValue instanceof AtlasObjectId);
+            AtlasObjectId referencedObjectId = (AtlasObjectId) refValue;
+            assertEquals(referencedObjectId.getGuid(), expectedGuid);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateHardDeleteV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateHardDeleteV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateHardDeleteV1Test.java
new file mode 100644
index 0000000..d54adeb
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateHardDeleteV1Test.java
@@ -0,0 +1,75 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.store.graph.v1;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.type.AtlasTypeUtil;
+import org.testng.annotations.Guice;
+
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Inverse reference update test with {@link HardDeleteHandlerV1}
+ */
+@Guice(modules = TestModules.HardDeleteModule.class)
+public class InverseReferenceUpdateHardDeleteV1Test extends InverseReferenceUpdateV1Test {
+
+    @Override
+    protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception {
+
+        // Max should have been removed from the subordinates list, leaving only John.
+        verifyReferenceList(jane, "subordinates", ImmutableList.of(nameIdMap.get("John")));
+    }
+
+    @Override
+    protected void verify_testInverseReferenceAutoUpdate_NonCompositeManyToOne(AtlasEntity a1, AtlasEntity a2, AtlasEntity a3, AtlasEntity b) {
+
+        verifyReferenceValue(a1, "oneB", null);
+
+        verifyReferenceValue(a2, "oneB", null);
+
+        verifyReferenceList(b, "manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a3)));
+    }
+
+    @Override
+    protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
+
+        verifyReferenceValue(a1, "b", null);
+    }
+
+    @Override
+    protected void verify_testInverseReferenceAutoUpdate_Map(AtlasEntity a1, AtlasEntity b1,
+        AtlasEntity b2, AtlasEntity b3) {
+
+        Object value = a1.getAttribute("mapToB");
+        assertTrue(value instanceof Map);
+        Map<String, AtlasObjectId> refMap = (Map<String, AtlasObjectId>) value;
+        assertEquals(refMap.size(), 1);
+        AtlasObjectId referencedEntityId = refMap.get("b3");
+        assertEquals(referencedEntityId, AtlasTypeUtil.getAtlasObjectId(b3));
+        verifyReferenceValue(b1, "mappedFromA", null);
+        verifyReferenceValue(b2, "mappedFromA", null);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateSoftDeleteV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateSoftDeleteV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateSoftDeleteV1Test.java
new file mode 100644
index 0000000..884ab54
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateSoftDeleteV1Test.java
@@ -0,0 +1,78 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.store.graph.v1;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.type.AtlasTypeUtil;
+import org.testng.annotations.Guice;
+
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+
+/**
+ * Inverse reference update test with {@link SoftDeleteHandlerV1}
+ */
+@Guice(modules = TestModules.SoftDeleteModule.class)
+public class InverseReferenceUpdateSoftDeleteV1Test extends InverseReferenceUpdateV1Test {
+
+    @Override
+    protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(AtlasEntity jane)
+        throws Exception {
+
+        // Max is still in the subordinates list, as the edge still exists with state DELETED
+        verifyReferenceList(jane, "subordinates", ImmutableList.of(nameIdMap.get("John"), nameIdMap.get("Max")));
+    }
+
+    @Override
+    protected void verify_testInverseReferenceAutoUpdate_NonCompositeManyToOne(AtlasEntity a1,
+        AtlasEntity a2, AtlasEntity a3, AtlasEntity b) {
+
+        verifyReferenceValue(a1, "oneB", b.getGuid());
+
+        verifyReferenceValue(a2, "oneB", b.getGuid());
+
+        verifyReferenceList(b, "manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2), AtlasTypeUtil.getAtlasObjectId(a3)));
+    }
+
+    @Override
+    protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
+
+        verifyReferenceValue(a1, "b", b.getGuid());
+    }
+
+    @Override
+    protected void verify_testInverseReferenceAutoUpdate_Map(AtlasEntity a1, AtlasEntity b1,
+        AtlasEntity b2, AtlasEntity b3) {
+
+        Object value = a1.getAttribute("mapToB");
+        assertTrue(value instanceof Map);
+        Map<String, AtlasObjectId> refMap = (Map<String, AtlasObjectId>) value;
+        assertEquals(refMap.size(), 3);
+        AtlasObjectId referencedEntityId = refMap.get("b3");
+        assertEquals(referencedEntityId, AtlasTypeUtil.getAtlasObjectId(b3));
+        verifyReferenceValue(b1, "mappedFromA", a1.getGuid());
+        verifyReferenceValue(b2, "mappedFromA", a1.getGuid());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateV1Test.java
new file mode 100644
index 0000000..2c21638
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/InverseReferenceUpdateV1Test.java
@@ -0,0 +1,374 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.store.graph.v1;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.TestUtilsV2;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
+import org.apache.atlas.model.instance.AtlasEntityHeader;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.model.instance.EntityMutationResponse;
+import org.apache.atlas.model.typedef.AtlasTypesDef;
+import org.apache.atlas.repository.graph.AtlasGraphProvider;
+import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
+import org.apache.atlas.repository.store.graph.AtlasEntityStore;
+import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasEntityType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.atlas.type.AtlasTypeUtil;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import javax.inject.Inject;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import static org.apache.atlas.TestUtilsV2.NAME;
+
+/**
+ * Test automatic inverse reference updating in V1 (V2?) code path.
+ *
+ */
+public abstract class InverseReferenceUpdateV1Test {
+    @Inject
+    AtlasTypeRegistry typeRegistry;
+
+    @Inject
+    AtlasTypeDefStore typeDefStore;
+
+    @Inject
+    AtlasEntityStore entityStore;
+
+    private AtlasEntitiesWithExtInfo deptEntity;
+
+    protected Map<String, AtlasObjectId> nameIdMap = new HashMap<>();
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        RequestContextV1.clear();
+        RequestContextV1.get().setUser(TestUtilsV2.TEST_USER);
+
+        AtlasTypesDef[] testTypesDefs = new AtlasTypesDef[] { TestUtilsV2.defineDeptEmployeeTypes(),
+                                                              TestUtilsV2.defineInverseReferenceTestTypes()
+                                                            };
+
+        for (AtlasTypesDef typesDef : testTypesDefs) {
+            AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(typesDef, typeRegistry);
+
+            if (!typesToCreate.isEmpty()) {
+                typeDefStore.createTypesDef(typesToCreate);
+            }
+        }
+
+        deptEntity = TestUtilsV2.createDeptEg2();
+        init();
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(deptEntity), false);
+        for (AtlasEntityHeader entityHeader : response.getCreatedEntities()) {
+            nameIdMap.put((String)entityHeader.getAttribute(NAME), AtlasTypeUtil.getAtlasObjectId(entityHeader));
+        }
+    }
+
+    @AfterClass
+    public void clear() {
+        AtlasGraphProvider.cleanup();
+    }
+
+    @BeforeMethod
+    public void init() throws Exception {
+        RequestContextV1.clear();
+        RequestContextV1.get().setUser(TestUtilsV2.TEST_USER);
+    }
+
+    @Test
+    public void testInverseReferenceAutoUpdate_NonComposite_OneToMany() throws Exception {
+        AtlasObjectId juliusId = nameIdMap.get("Julius");
+
+        // Change Max's Employee.manager reference to Julius and apply the change as a partial update.
+        // This should also update Julius to add Max to the inverse Manager.subordinates reference.
+        AtlasEntity maxEntityForUpdate = new AtlasEntity(TestUtilsV2.EMPLOYEE_TYPE);
+        maxEntityForUpdate.setAttribute("manager", juliusId);
+        AtlasEntityType employeeType = typeRegistry.getEntityTypeByName(TestUtilsV2.EMPLOYEE_TYPE);
+        Map<String, Object> uniqAttributes = Collections.<String, Object>singletonMap("name", "Max");
+        EntityMutationResponse updateResponse = entityStore.updateByUniqueAttributes(employeeType, uniqAttributes , new AtlasEntityWithExtInfo(maxEntityForUpdate));
+        List<AtlasEntityHeader> partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
+        // 3 entities should have been updated:
+        // * Max to change the Employee.manager reference
+        // * Julius to add Max to Manager.subordinates
+        // * Jane to remove Max from Manager.subordinates
+        assertEquals(partialUpdatedEntities.size(), 3);
+
+        AtlasObjectId maxId = nameIdMap.get("Max");
+        String janeGuid = nameIdMap.get("Jane").getGuid();
+        AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(maxId.getGuid(), juliusId.getGuid(), janeGuid));
+        AtlasEntity storedEntity = storedEntities.getEntity(maxId.getGuid());
+        verifyReferenceValue(storedEntity, "manager", juliusId.getGuid());
+        storedEntity = storedEntities.getEntity(juliusId.getGuid());
+        verifyReferenceList(storedEntity, "subordinates", ImmutableList.of(maxId));
+        storedEntity = storedEntities.getEntity(janeGuid);
+        verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(storedEntity);
+    }
+
+    protected abstract void verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception;
+
+    @Test
+    public void testInverseReferenceAutoUpdate_NonCompositeManyToOne() throws Exception {
+        AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
+        AtlasEntity a1 = new AtlasEntity("A");
+        a1.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity a2 = new AtlasEntity("A");
+        a2.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity a3 = new AtlasEntity("A");
+        a3.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity b = new AtlasEntity("B");
+
+        b.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+        atlasEntitiesWithExtInfo.addEntity(a1);
+        atlasEntitiesWithExtInfo.addEntity(a2);
+        atlasEntitiesWithExtInfo.addEntity(a3);
+        atlasEntitiesWithExtInfo.addEntity(b);
+        AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
+        EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);
+
+        AtlasEntity bForPartialUpdate = new AtlasEntity("B");
+        bForPartialUpdate.setAttribute("manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));
+        init();
+        response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
+        List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
+        // Verify 3 entities were updated:
+        // * set b.manyA reference to a1 and a2
+        // * set inverse a1.oneB reference to b
+        // * set inverse a2.oneB reference to b
+        assertEquals(partialUpdatedEntities.size(), 3);
+        AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
+        AtlasEntity storedEntity = storedEntities.getEntity(a1.getGuid());
+        verifyReferenceValue(storedEntity, "oneB", b.getGuid());
+
+        storedEntity = storedEntities.getEntity(a2.getGuid());
+        verifyReferenceValue(storedEntity, "oneB", b.getGuid());
+
+        storedEntity = storedEntities.getEntity(b.getGuid());
+        verifyReferenceList(storedEntity, "manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));
+
+        bForPartialUpdate.setAttribute("manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a3)));
+        init();
+        response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
+        partialUpdatedEntities = response.getPartialUpdatedEntities();
+        // Verify 4 entities were updated:
+        // * set b.manyA reference to a3
+        // * set inverse a3.oneB reference to b
+        // * disconnect inverse a1.oneB reference to b
+        // * disconnect inverse a2.oneB reference to b
+        assertEquals(partialUpdatedEntities.size(), 4);
+
+        init();
+        storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), a3.getGuid(), b.getGuid()));
+        verifyReferenceValue(storedEntities.getEntity(a3.getGuid()), "oneB", b.getGuid());
+
+        verify_testInverseReferenceAutoUpdate_NonCompositeManyToOne(storedEntities.getEntity(a1.getGuid()), storedEntities.getEntity(a2.getGuid()),
+            storedEntities.getEntity(a3.getGuid()), storedEntities.getEntity(b.getGuid()));
+    }
+
+    protected abstract void verify_testInverseReferenceAutoUpdate_NonCompositeManyToOne(AtlasEntity a1, AtlasEntity a2, AtlasEntity a3, AtlasEntity b);
+
+    @Test
+    public void testInverseReferenceAutoUpdate_NonComposite_OneToOne() throws Exception {
+        AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
+        AtlasEntity a1 = new AtlasEntity("A");
+        a1.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity a2 = new AtlasEntity("A");
+        a2.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity b = new AtlasEntity("B");
+        b.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+        atlasEntitiesWithExtInfo.addEntity(a1);
+        atlasEntitiesWithExtInfo.addEntity(a2);
+        atlasEntitiesWithExtInfo.addEntity(b);
+        AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
+        EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);
+
+        AtlasEntity bForPartialUpdate = new AtlasEntity("B");
+        bForPartialUpdate.setAttribute("a", AtlasTypeUtil.getAtlasObjectId(a1));
+        init();
+        response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
+        List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
+        // Verify 2 entities were updated:
+        // * set b.a reference to a1
+        // * set inverse a1.b reference to b
+        assertEquals(partialUpdatedEntities.size(), 2);
+        AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b.getGuid()));
+        AtlasEntity storedEntity = storedEntities.getEntity(a1.getGuid());
+        verifyReferenceValue(storedEntity, "b", b.getGuid());
+        storedEntity = storedEntities.getEntity(b.getGuid());
+        verifyReferenceValue(storedEntity, "a", a1.getGuid());
+
+        // Update b.a to reference a2.
+        bForPartialUpdate.setAttribute("a", AtlasTypeUtil.getAtlasObjectId(a2));
+        init();
+        response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
+        partialUpdatedEntities = response.getPartialUpdatedEntities();
+        // Verify 3 entities were updated:
+        // * set b.a reference to a2
+        // * set a2.b reference to b
+        // * disconnect a1.b reference
+        assertEquals(partialUpdatedEntities.size(), 3);
+        storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
+        storedEntity = storedEntities.getEntity(a2.getGuid());
+        verifyReferenceValue(storedEntity, "b", b.getGuid());
+        storedEntity = storedEntities.getEntity(b.getGuid());
+        verifyReferenceValue(storedEntity, "a", a2.getGuid());
+        storedEntity = storedEntities.getEntity(a1.getGuid());
+        Object refValue = storedEntity.getAttribute("b");
+        verify_testInverseReferenceAutoUpdate_NonComposite_OneToOne(storedEntities.getEntity(a1.getGuid()), storedEntities.getEntity(b.getGuid()));
+    }
+
+    protected abstract void verify_testInverseReferenceAutoUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b);
+
+    @Test
+    public void testInverseReferenceAutoUpdate_NonComposite_ManyToMany() throws Exception {
+        AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
+        AtlasEntity a1 = new AtlasEntity("A");
+        a1.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity a2 = new AtlasEntity("A");
+        a2.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity a3 = new AtlasEntity("A");
+        a3.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity b1 = new AtlasEntity("B");
+        b1.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity b2 = new AtlasEntity("B");
+        b2.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+        atlasEntitiesWithExtInfo.addEntity(a1);
+        atlasEntitiesWithExtInfo.addEntity(a2);
+        atlasEntitiesWithExtInfo.addEntity(a3);
+        atlasEntitiesWithExtInfo.addEntity(b1);
+        atlasEntitiesWithExtInfo.addEntity(b2);
+        AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
+        EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);
+
+        AtlasEntity b1ForPartialUpdate = new AtlasEntity("B");
+        b1ForPartialUpdate.setAttribute("manyToManyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));
+        init();
+        response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b1.getAttribute(NAME)), new AtlasEntityWithExtInfo(b1ForPartialUpdate));
+        List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
+        assertEquals(partialUpdatedEntities.size(), 3);
+        AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b1.getGuid()));
+        AtlasEntity storedEntity = storedEntities.getEntity(b1.getGuid());
+        verifyReferenceList(storedEntity, "manyToManyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));
+        storedEntity = storedEntities.getEntity(a1.getGuid());
+        verifyReferenceList(storedEntity, "manyB", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(b1)));
+        storedEntity = storedEntities.getEntity(a2.getGuid());
+        verifyReferenceList(storedEntity, "manyB", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(b1)));
+    }
+
+    @Test
+    public void testInverseReferenceAutoUpdate_Map() throws Exception {
+        AtlasEntity a1 = new AtlasEntity("A");
+        a1.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity b1 = new AtlasEntity("B");
+        b1.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity b2 = new AtlasEntity("B");
+        b2.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntity b3 = new AtlasEntity("B");
+        b3.setAttribute(NAME, TestUtilsV2.randomString());
+        AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+        atlasEntitiesWithExtInfo.addEntity(a1);
+        atlasEntitiesWithExtInfo.addEntity(b1);
+        atlasEntitiesWithExtInfo.addEntity(b2);
+        atlasEntitiesWithExtInfo.addEntity(b3);
+        AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
+        EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);
+
+        AtlasEntityType aType = typeRegistry.getEntityTypeByName("A");
+        AtlasEntity aForPartialUpdate = new AtlasEntity("A");
+        aForPartialUpdate.setAttribute("mapToB", ImmutableMap.<String, AtlasObjectId>of("b1", AtlasTypeUtil.getAtlasObjectId(b1), "b2", AtlasTypeUtil.getAtlasObjectId(b2)));
+        init();
+        response = entityStore.updateByUniqueAttributes(aType, Collections.<String, Object>singletonMap(NAME, a1.getAttribute(NAME)), new AtlasEntityWithExtInfo(aForPartialUpdate));
+        List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
+        // Verify 3 entities were updated:
+        // * set a1.mapToB to "b1"->b1, "b2"->b2
+        // * set b1.mappedFromA to a1
+        // * set b2.mappedFromA to a1
+        assertEquals(partialUpdatedEntities.size(), 3);
+        AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b2.getGuid(), b1.getGuid()));
+        AtlasEntity storedEntity = storedEntities.getEntity(a1.getGuid());
+        Object value = storedEntity.getAttribute("mapToB");
+        assertTrue(value instanceof Map);
+        Map<String, AtlasObjectId> refMap = (Map<String, AtlasObjectId>) value;
+        assertEquals(refMap.size(), 2);
+        AtlasObjectId referencedEntityId = refMap.get("b1");
+        assertEquals(referencedEntityId, AtlasTypeUtil.getAtlasObjectId(b1));
+        referencedEntityId = refMap.get("b2");
+        assertEquals(referencedEntityId, AtlasTypeUtil.getAtlasObjectId(b2));
+        storedEntity = storedEntities.getEntity(b1.getGuid());
+        verifyReferenceValue(storedEntity, "mappedFromA", a1.getGuid());
+        storedEntity = storedEntities.getEntity(b2.getGuid());
+        verifyReferenceValue(storedEntity, "mappedFromA", a1.getGuid());
+
+        aForPartialUpdate.setAttribute("mapToB", ImmutableMap.<String, AtlasObjectId>of("b3", AtlasTypeUtil.getAtlasObjectId(b3)));
+        init();
+        response = entityStore.updateByUniqueAttributes(aType, Collections.<String, Object>singletonMap(NAME, a1.getAttribute(NAME)), new AtlasEntityWithExtInfo(aForPartialUpdate));
+        partialUpdatedEntities = response.getPartialUpdatedEntities();
+        // Verify 4 entities were updated:
+        // * set a1.mapToB to "b3"->b3
+        // * set b3.mappedFromA to a1
+        // * disconnect b1.mappedFromA
+        // * disconnect b2.mappedFromA
+        assertEquals(partialUpdatedEntities.size(), 4);
+        storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b2.getGuid(), b1.getGuid(), b3.getGuid()));
+        AtlasEntity storedB3 = storedEntities.getEntity(b3.getGuid());
+        verifyReferenceValue(storedB3, "mappedFromA", a1.getGuid());
+        verify_testInverseReferenceAutoUpdate_Map(storedEntities.getEntity(a1.getGuid()), storedEntities.getEntity(b1.getGuid()), storedEntities.getEntity(b2.getGuid()), storedB3);
+    }
+
+    protected abstract void verify_testInverseReferenceAutoUpdate_Map(AtlasEntity a1, AtlasEntity b1, AtlasEntity b2, AtlasEntity b3);
+
+    protected void verifyReferenceValue(AtlasEntity entity, String refName, String expectedGuid) {
+        Object refValue = entity.getAttribute(refName);
+        if (expectedGuid == null) {
+            assertNull(refValue);
+        }
+        else {
+            assertTrue(refValue instanceof AtlasObjectId);
+            AtlasObjectId referencedObjectId = (AtlasObjectId) refValue;
+            assertEquals(referencedObjectId.getGuid(), expectedGuid);
+        }
+    }
+
+    protected void verifyReferenceList(AtlasEntity entity, String refName, List<AtlasObjectId> expectedValues) {
+        Object refValue = entity.getAttribute(refName);
+        assertTrue(refValue instanceof List);
+        List<AtlasObjectId> refList = (List<AtlasObjectId>) refValue;
+        assertEquals(refList.size(), expectedValues.size());
+        if (expectedValues.size() > 0) {
+            assertTrue(refList.containsAll(expectedValues));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/userprofile/UserProfileServiceTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/userprofile/UserProfileServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/userprofile/UserProfileServiceTest.java
new file mode 100644
index 0000000..0532f16
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/userprofile/UserProfileServiceTest.java
@@ -0,0 +1,280 @@
+/**
+ * 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.userprofile;
+
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.SearchFilter;
+import org.apache.atlas.model.discovery.SearchParameters;
+import org.apache.atlas.model.profile.AtlasUserProfile;
+import org.apache.atlas.model.profile.AtlasUserSavedSearch;
+import org.apache.atlas.model.typedef.AtlasTypesDef;
+import org.apache.atlas.repository.util.FilterUtil;
+import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.atlas.model.profile.AtlasUserSavedSearch.SavedSearchType.BASIC;
+import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.loadModelFromJson;
+import static org.testng.Assert.*;
+
+@Guice(modules = TestModules.TestOnlyModule.class)
+public class UserProfileServiceTest {
+    private UserProfileService userProfileService;
+    private AtlasTypeDefStore  typeDefStore;
+    private int                max_searches = 4;
+
+    @Inject
+    public void UserProfileServiceTest(AtlasTypeRegistry  typeRegistry,
+                                       AtlasTypeDefStore  typeDefStore,
+                                       UserProfileService userProfileService) throws IOException, AtlasBaseException {
+        this.typeDefStore       = typeDefStore;
+        this.userProfileService = userProfileService;
+
+        loadModelFromJson("0010-base_model.json", typeDefStore, typeRegistry);
+    }
+
+    @Test
+    public void filterInternalType() throws AtlasBaseException {
+        SearchFilter searchFilter = new SearchFilter();
+        AtlasTypesDef filteredTypeDefs = typeDefStore.searchTypesDef(searchFilter);
+        int maxTypeDefs = filteredTypeDefs.getEntityDefs().size();
+
+        FilterUtil.addParamsToHideInternalType(searchFilter);
+        filteredTypeDefs = typeDefStore.searchTypesDef(searchFilter);
+
+        assertNotNull(filteredTypeDefs);
+        assertEquals(filteredTypeDefs.getEntityDefs().size(), maxTypeDefs - 3);
+    }
+
+    @Test
+    public void createsNewProfile() throws AtlasBaseException {
+        int i = 0;
+        assertSaveLoadUserProfile(i++);
+        assertSaveLoadUserProfile(i);
+    }
+
+    @Test(dependsOnMethods = { "createsNewProfile", "savesQueryForAnNonExistentUser" }, expectedExceptions = AtlasBaseException.class)
+    public void atteptsToAddAlreadyExistingQueryForAnExistingUser() throws AtlasBaseException {
+        SearchParameters expectedSearchParameter = getActualSearchParameters();
+
+        for (int i = 0; i < 2; i++) {
+            String userName = getIndexBasedUserName(i);
+
+            for (int j = 0; j < max_searches; j++) {
+                String queryName = getIndexBasedQueryName(j);
+                AtlasUserSavedSearch expected = getDefaultSavedSearch(userName, queryName, expectedSearchParameter);
+                AtlasUserSavedSearch actual = userProfileService.addSavedSearch(expected);
+
+                assertNotNull(actual);
+                assertNotNull(actual.getGuid());
+                assertEquals(actual.getOwnerName(), expected.getOwnerName());
+                assertEquals(actual.getName(), expected.getName());
+                assertEquals(actual.getSearchType(), expected.getSearchType());
+                assertEquals(actual.getSearchParameters(), expected.getSearchParameters());
+            }
+        }
+    }
+
+    @Test(dependsOnMethods = { "createsNewProfile", "savesQueryForAnNonExistentUser", "atteptsToAddAlreadyExistingQueryForAnExistingUser" })
+    public void savesExistingQueryForAnExistingUser() throws AtlasBaseException {
+        SearchParameters expectedSearchParameter = getActualSearchParameters();
+
+        for (int i = 0; i < 2; i++) {
+            String userName = getIndexBasedUserName(i);
+
+            for (int j = 4; j < max_searches + 6; j++) {
+                String queryName = getIndexBasedQueryName(j);
+                AtlasUserSavedSearch actual = userProfileService.addSavedSearch(getDefaultSavedSearch(userName, queryName, expectedSearchParameter));
+                assertNotNull(actual);
+
+                AtlasUserSavedSearch savedSearch = userProfileService.getSavedSearch(userName, queryName);
+                assertNotNull(savedSearch);
+                assertEquals(savedSearch.getSearchParameters(), expectedSearchParameter);
+            }
+        }
+    }
+
+    private SearchParameters getActualSearchParameters() {
+        SearchParameters sp = new SearchParameters();
+        sp.setClassification("test-classification");
+        sp.setQuery("g.v().has('__guid').__guid.toList()");
+        sp.setLimit(10);
+        sp.setTypeName("some-type");
+
+        return sp;
+    }
+
+    @Test(dependsOnMethods = "createsNewProfile")
+    public void savesQueryForAnNonExistentUser() throws AtlasBaseException {
+        String expectedUserName = getIndexBasedUserName(0);
+        String expectedQueryName = "testQuery";
+        SearchParameters expectedSearchParam = getActualSearchParameters();
+        AtlasUserSavedSearch expectedSavedSearch = getDefaultSavedSearch(expectedUserName, expectedQueryName, expectedSearchParam);
+
+        AtlasUserSavedSearch actual = userProfileService.addSavedSearch(expectedSavedSearch);
+        assertEquals(actual.getOwnerName(), expectedUserName);
+        assertEquals(actual.getName(), expectedQueryName);
+    }
+
+    private AtlasUserSavedSearch getDefaultSavedSearch(String userName, String queryName, SearchParameters expectedSearchParam) {
+        return new AtlasUserSavedSearch(userName, queryName,
+                BASIC, expectedSearchParam);
+    }
+
+    @Test(dependsOnMethods = "createsNewProfile")
+    public void savesMultipleQueriesForUser() throws AtlasBaseException {
+        final String userName = getIndexBasedUserName(0);
+        createUserWithSavedQueries(userName);
+    }
+
+    private void createUserWithSavedQueries(String userName) throws AtlasBaseException {
+        SearchParameters actualSearchParameter = getActualSearchParameters();
+
+        saveQueries(userName, actualSearchParameter);
+        for (int i = 0; i < max_searches; i++) {
+            AtlasUserSavedSearch savedSearch = userProfileService.getSavedSearch(userName, getIndexBasedQueryName(i));
+            assertEquals(savedSearch.getName(), getIndexBasedQueryName(i));
+            assertEquals(savedSearch.getSearchParameters(), actualSearchParameter);
+        }
+    }
+
+    private void saveQueries(String userName, SearchParameters sp) throws AtlasBaseException {
+        for (int i = 0; i < max_searches; i++) {
+            userProfileService.addSavedSearch(getDefaultSavedSearch(userName, getIndexBasedQueryName(i), sp));
+        }
+    }
+
+    @Test(dependsOnMethods = {"createsNewProfile", "savesMultipleQueriesForUser"})
+    public void verifyQueryNameListForUser() throws AtlasBaseException {
+        final String userName = getIndexBasedUserName(0);
+
+        List<AtlasUserSavedSearch> list = userProfileService.getSavedSearches(userName);
+        List<String> names = getIndexBasedQueryNamesList();
+        for (int i = 0; i < names.size(); i++) {
+            assertTrue(names.contains(list.get(i).getName()), list.get(i).getName() + " failed!");
+        }
+    }
+
+    @Test(dependsOnMethods = {"createsNewProfile", "savesMultipleQueriesForUser"}, enabled = false)
+    public void verifyQueryConversionFromJSON() throws AtlasBaseException {
+        List<AtlasUserSavedSearch> list = userProfileService.getSavedSearches("first-0");
+
+        for (int i = 0; i < max_searches; i++) {
+            SearchParameters sp = list.get(i).getSearchParameters();
+            String json = AtlasType.toJson(sp);
+            assertEquals(AtlasType.toJson(getActualSearchParameters()).replace("\n", "").replace(" ", ""), json);
+        }
+    }
+
+    @Test(dependsOnMethods = {"createsNewProfile", "savesMultipleQueriesForUser"})
+    public void updateSearch() throws AtlasBaseException {
+        final String queryName = getIndexBasedQueryName(0);
+        String userName = getIndexBasedUserName(0);
+        AtlasUserSavedSearch expected = userProfileService.getSavedSearch(userName, queryName);
+        assertNotNull(expected);
+
+        SearchParameters sp = expected.getSearchParameters();
+        sp.setClassification("new-classification");
+
+        AtlasUserSavedSearch actual = userProfileService.updateSavedSearch(expected);
+
+        assertNotNull(actual);
+        assertNotNull(actual.getSearchParameters());
+        assertEquals(actual.getSearchParameters().getClassification(), expected.getSearchParameters().getClassification());
+    }
+
+    @Test(dependsOnMethods = {"createsNewProfile", "savesMultipleQueriesForUser", "verifyQueryNameListForUser"}, expectedExceptions = AtlasBaseException.class)
+    public void deleteUsingGuid() throws AtlasBaseException {
+        final String queryName = getIndexBasedQueryName(1);
+        String userName = getIndexBasedUserName(0);
+
+        AtlasUserSavedSearch expected = userProfileService.getSavedSearch(userName, queryName);
+        assertNotNull(expected);
+
+        userProfileService.deleteSavedSearch(expected.getGuid());
+        userProfileService.getSavedSearch(userName, queryName);
+    }
+
+    @Test(dependsOnMethods = {"createsNewProfile", "savesMultipleQueriesForUser", "verifyQueryNameListForUser"})
+    public void deleteSavedQuery() throws AtlasBaseException {
+        final String userName = getIndexBasedUserName(0);
+        AtlasUserProfile expected = userProfileService.getUserProfile(userName);
+        assertNotNull(expected);
+
+        int new_max_searches = expected.getSavedSearches().size();
+        String queryNameToBeDeleted = getIndexBasedQueryName(max_searches - 2);
+        userProfileService.deleteSearchBySearchName(userName, queryNameToBeDeleted);
+
+        List<AtlasUserSavedSearch> savedSearchList = userProfileService.getSavedSearches(userName);
+        assertEquals(savedSearchList.size(), new_max_searches - 1);
+    }
+
+    @Test(dependsOnMethods = {"createsNewProfile", "savesMultipleQueriesForUser", "verifyQueryNameListForUser"})
+    void deleteUser() throws AtlasBaseException {
+        String userName = getIndexBasedUserName(1);
+
+        userProfileService.deleteUserProfile(userName);
+        try {
+            userProfileService.getUserProfile(userName);
+        }
+        catch(AtlasBaseException ex) {
+            assertEquals(ex.getAtlasErrorCode().name(), AtlasErrorCode.INSTANCE_BY_UNIQUE_ATTRIBUTE_NOT_FOUND.name());
+        }
+    }
+
+    private void assertSaveLoadUserProfile(int i) throws AtlasBaseException {
+        String s = String.valueOf(i);
+        AtlasUserProfile expected = getAtlasUserProfile(i);
+
+        AtlasUserProfile actual = userProfileService.saveUserProfile(expected);
+        assertNotNull(actual);
+        assertEquals(expected.getName(), actual.getName());
+        assertEquals(expected.getFullName(), actual.getFullName());
+        assertNotNull(actual.getGuid());
+    }
+
+    public static AtlasUserProfile getAtlasUserProfile(Integer s) {
+        return new AtlasUserProfile(getIndexBasedUserName(s), String.format("first-%s last-%s", s, s));
+    }
+
+    private static String getIndexBasedUserName(Integer i) {
+        return String.format("first-%s", i.toString());
+    }
+
+    private static String getIndexBasedQueryName(Integer i) {
+        return String.format("testQuery-%s", i.toString());
+    }
+
+    public List<String> getIndexBasedQueryNamesList() {
+        List<String> list = new ArrayList<>();
+        for (int i = 0; i < max_searches; i++) {
+            list.add(getIndexBasedQueryName(i));
+        }
+
+        return list;
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/services/MetricsServiceTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/services/MetricsServiceTest.java b/repository/src/test/java/org/apache/atlas/services/MetricsServiceTest.java
new file mode 100644
index 0000000..5165bcb
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/services/MetricsServiceTest.java
@@ -0,0 +1,123 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.services;
+
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.metrics.AtlasMetrics;
+import org.apache.atlas.repository.graphdb.AtlasGraph;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.commons.configuration.Configuration;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+public class MetricsServiceTest {
+    private Configuration mockConfig = mock(Configuration.class);
+    private AtlasTypeRegistry mockTypeRegistry = mock(AtlasTypeRegistry.class);
+    private AtlasGraph mockGraph = mock(AtlasGraph.class);
+    private MetricsService metricsService;
+
+    private List<Map> mockMapList = new ArrayList<>();
+    private Number mockCount = 10;
+
+    @BeforeClass
+    public void init() throws AtlasBaseException {
+        Map<String, Object> mockMap = new HashMap<>();
+        mockMap.put("a", 1);
+        mockMap.put("b", 2);
+        mockMap.put("c", 3);
+        mockMapList.add(mockMap);
+
+        when(mockConfig.getInt(anyString(), anyInt())).thenReturn(5);
+        assertEquals(mockConfig.getInt("test", 1), 5);
+        when(mockConfig.getString(anyString(), anyString()))
+                .thenReturn("count()", "count()", "count()", "count()", "count()", "toList()", "count()", "toList()");
+        when(mockTypeRegistry.getAllEntityDefNames()).thenReturn(Arrays.asList("a", "b", "c"));
+        setupMockGraph();
+
+        metricsService = new MetricsService(mockConfig, mockGraph);
+    }
+
+    private void setupMockGraph() throws AtlasBaseException {
+        if (mockGraph == null) mockGraph = mock(AtlasGraph.class);
+        when(mockGraph.executeGremlinScript(anyString(), eq(false))).thenAnswer(new Answer<Object>() {
+            @Override
+            public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
+                if (((String)invocationOnMock.getArguments()[0]).contains("count()")) {
+                    return mockCount;
+                } else {
+                    return mockMapList;
+                }
+            }
+        });
+    }
+
+    @Test
+    public void testGetMetrics() throws InterruptedException, AtlasBaseException {
+        assertNotNull(metricsService);
+        AtlasMetrics metrics = metricsService.getMetrics(false);
+        assertNotNull(metrics);
+        Number aCount = metrics.getMetric("entity", "a");
+        assertNotNull(aCount);
+        assertEquals(aCount, 1);
+
+        Number bCount = metrics.getMetric("entity", "b");
+        assertNotNull(bCount);
+        assertEquals(bCount, 2);
+
+        Number cCount = metrics.getMetric("entity", "c");
+        assertNotNull(cCount);
+        assertEquals(cCount, 3);
+
+        Number aTags = metrics.getMetric("tag", "a");
+        assertNotNull(aTags);
+        assertEquals(aTags, 1);
+
+        Number bTags = metrics.getMetric("tag", "b");
+        assertNotNull(bTags);
+        assertEquals(bTags, 2);
+
+        Number cTags = metrics.getMetric("tag", "c");
+        assertNotNull(cTags);
+        assertEquals(cTags, 3);
+
+        verify(mockGraph, atLeastOnce()).executeGremlinScript(anyString(), anyBoolean());
+
+        // Subsequent call within the cache timeout window
+        metricsService.getMetrics(false);
+        verifyZeroInteractions(mockGraph);
+
+        // Now test the cache refresh
+        Thread.sleep(6000);
+        metricsService.getMetrics(true);
+        verify(mockGraph, atLeastOnce()).executeGremlinScript(anyString(), anyBoolean());
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/utils/ObjectUpdateSynchronizerTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/utils/ObjectUpdateSynchronizerTest.java b/repository/src/test/java/org/apache/atlas/utils/ObjectUpdateSynchronizerTest.java
new file mode 100644
index 0000000..03ebae4
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/utils/ObjectUpdateSynchronizerTest.java
@@ -0,0 +1,218 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.utils;
+
+import org.apache.atlas.GraphTransactionInterceptor;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.RandomStringUtils;
+import org.springframework.util.CollectionUtils;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+public class ObjectUpdateSynchronizerTest {
+    private static final GraphTransactionInterceptor.ObjectUpdateSynchronizer objectUpdateSynchronizer = new GraphTransactionInterceptor.ObjectUpdateSynchronizer();
+
+    private final List<Integer> outputList = new ArrayList<>();
+    private final int MAX_COUNT = 10;
+
+    class CounterThread extends Thread {
+        String ids[];
+        public CounterThread(String id) {
+            this.ids = new String[1];
+            this.ids[0] = id;
+        }
+
+        public void setIds(String... ids) {
+            this.ids = ids;
+        }
+
+        public void run() {
+            objectUpdateSynchronizer.lockObject(CollectionUtils.arrayToList(ids));
+            for (int i = 0; i < MAX_COUNT; i++) {
+                outputList.add(i);
+                RandomStringUtils.randomAlphabetic(20);
+            }
+
+            objectUpdateSynchronizer.releaseLockedObjects();
+        }
+    }
+
+    @BeforeMethod
+    public void clearOutputList() {
+        outputList.clear();
+    }
+
+    @Test
+    public void singleThreadRun() throws InterruptedException {
+        verifyMultipleThreadRun(1);
+    }
+
+    @Test
+    public void twoThreadsAccessingDifferntGuids_DoNotSerialize() throws InterruptedException {
+        CounterThread th[] = getCounterThreads(false, 2);
+
+        startCounterThreads(th);
+        waitForThreadsToEnd(th);
+        assertArrayNotEquals(populateExpectedArrayOutput(2));
+    }
+
+    @Test
+    public void twoThreadsAccessingSameGuid_Serialize() throws InterruptedException {
+        verifyMultipleThreadRun(2);
+    }
+
+    @Test
+    public void severalThreadsAccessingSameGuid_Serialize() throws InterruptedException {
+        verifyMultipleThreadRun(10);
+    }
+
+    @Test
+    public void severalThreadsSequentialAccessingListOfGuids() throws InterruptedException {
+        CounterThread th[] = getCounterThreads(false, 10);
+        int i = 0;
+        th[i++].setIds("1", "2", "3", "4", "5");
+        th[i++].setIds("1", "2", "3", "4");
+        th[i++].setIds("1", "2", "3");
+        th[i++].setIds("1", "2");
+        th[i++].setIds("1");
+        th[i++].setIds("1", "2");
+        th[i++].setIds("1", "2", "3");
+        th[i++].setIds("1", "2", "3", "4");
+        th[i++].setIds("1", "2", "3", "4", "5");
+        th[i++].setIds("1");
+
+        startCounterThreads(th);
+        waitForThreadsToEnd(th);
+        assertArrayEquals(populateExpectedArrayOutput(th.length));
+    }
+
+    @Test
+    public void severalThreadsNonSequentialAccessingListOfGuids() throws InterruptedException {
+        CounterThread th[] = getCounterThreads(false, 5);
+        int i = 0;
+        th[i++].setIds("2", "1", "3", "4", "5");
+        th[i++].setIds("3", "2", "4", "1");
+        th[i++].setIds("2", "3", "1");
+        th[i++].setIds("1", "2");
+        th[i++].setIds("1");
+
+        startCounterThreads(th);
+        waitForThreadsToEnd(th);
+        assertArrayEquals(populateExpectedArrayOutput(th.length));
+    }
+
+    @Test
+    public void severalThreadsAccessingOverlappingListOfGuids() throws InterruptedException {
+        CounterThread th[] = getCounterThreads(false, 5);
+        int i = 0;
+        th[i++].setIds("1", "2", "3", "4", "5");
+        th[i++].setIds("3", "4", "5", "6");
+        th[i++].setIds("5", "6", "7");
+        th[i++].setIds("7", "8");
+        th[i++].setIds("8");
+
+        startCounterThreads(th);
+        waitForThreadsToEnd(th);
+        assertArrayNotEquals(populateExpectedArrayOutput(th.length));
+    }
+
+
+    @Test
+    public void severalThreadsAccessingOverlappingListOfGuids2() throws InterruptedException {
+        CounterThread th[] = getCounterThreads(false, 3);
+        int i = 0;
+        th[i++].setIds("1", "2", "3", "4", "5");
+        th[i++].setIds("6", "7", "8", "9");
+        th[i++].setIds("4", "5", "6");
+
+        startCounterThreads(th);
+        waitForThreadsToEnd(th);
+        assertArrayNotEquals(populateExpectedArrayOutput(th.length));
+    }
+
+    @Test
+    public void severalThreadsAccessingOverlappingListOfGuidsEnsuringSerialOutput() throws InterruptedException {
+        CounterThread th[] = getCounterThreads(false, 5);
+        int i = 0;
+        th[i++].setIds("1", "2", "3", "4", "7");
+        th[i++].setIds("3", "4", "5", "7");
+        th[i++].setIds("5", "6", "7");
+        th[i++].setIds("7", "8");
+        th[i++].setIds("7");
+
+        startCounterThreads(th);
+        waitForThreadsToEnd(th);
+        assertArrayEquals(populateExpectedArrayOutput(th.length));
+    }
+
+    private void verifyMultipleThreadRun(int limit) throws InterruptedException {
+        CounterThread[] th = getCounterThreads(limit);
+        startCounterThreads(th);
+        waitForThreadsToEnd(th);
+        assertArrayEquals(populateExpectedArrayOutput(limit));
+    }
+
+    private void startCounterThreads(CounterThread[] th) {
+        for (int i = 0; i < th.length; i++) {
+            th[i].start();
+        }
+    }
+    private CounterThread[] getCounterThreads(int limit) {
+        return getCounterThreads(true, limit);
+    }
+
+    private CounterThread[] getCounterThreads(boolean sameId, int limit) {
+        CounterThread th[] = new CounterThread[limit];
+        for (Integer i = 0; i < limit; i++) {
+            th[i] = new CounterThread(sameId ? "1" : i.toString());
+        }
+        return th;
+    }
+
+
+    private void assertArrayEquals(List<Integer> expected) {
+        assertEquals(outputList.toArray(), expected.toArray());
+    }
+
+    private void assertArrayNotEquals(List<Integer> expected) {
+        assertFalse(ArrayUtils.isEquals(outputList.toArray(), expected));
+    }
+
+    private void waitForThreadsToEnd(CounterThread... threads) throws InterruptedException {
+        for (Thread t : threads) {
+            t.join();
+        }
+    }
+
+    private List<Integer> populateExpectedArrayOutput(int limit) {
+        List<Integer> list = new ArrayList<>();
+        for (int i = 0; i < limit*MAX_COUNT; i+=MAX_COUNT) {
+            for (int j = 0; j < MAX_COUNT; j++) {
+                list.add(j);
+            }
+        }
+
+        return list;
+    }
+}


[3/5] atlas git commit: ATLAS-2251: restored bunch of deleted tests

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java
new file mode 100644
index 0000000..fd1b6db
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java
@@ -0,0 +1,1043 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.store.graph.v1;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.TestUtilsV2;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.instance.AtlasClassification;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityExtInfo;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
+import org.apache.atlas.model.instance.AtlasEntityHeader;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.model.instance.AtlasStruct;
+import org.apache.atlas.model.instance.EntityMutationResponse;
+import org.apache.atlas.model.instance.EntityMutations;
+import org.apache.atlas.model.instance.EntityMutations.EntityOperation;
+import org.apache.atlas.model.typedef.AtlasClassificationDef;
+import org.apache.atlas.model.typedef.AtlasEntityDef;
+import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
+import org.apache.atlas.model.typedef.AtlasTypesDef;
+import org.apache.atlas.repository.graph.AtlasGraphProvider;
+import org.apache.atlas.repository.graph.GraphBackedSearchIndexer;
+import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
+import org.apache.atlas.repository.store.graph.AtlasEntityStore;
+import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasArrayType;
+import org.apache.atlas.type.AtlasMapType;
+import org.apache.atlas.type.AtlasStructType;
+import org.apache.atlas.type.AtlasType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.atlas.type.AtlasTypeUtil;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeTest;
+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.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.atlas.TestUtilsV2.COLUMNS_ATTR_NAME;
+import static org.apache.atlas.TestUtilsV2.COLUMN_TYPE;
+import static org.apache.atlas.TestUtilsV2.NAME;
+import static org.apache.atlas.TestUtilsV2.randomString;
+import static org.apache.atlas.TestUtilsV2.STORAGE_DESC_TYPE;
+import static org.apache.atlas.TestUtilsV2.TABLE_TYPE;
+import static org.mockito.Mockito.mock;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+@Guice(modules = TestModules.TestOnlyModule.class)
+public class AtlasEntityStoreV1Test {
+    private static final Logger LOG = LoggerFactory.getLogger(AtlasEntityStoreV1Test.class);
+
+    @Inject
+    AtlasTypeRegistry typeRegistry;
+
+    @Inject
+    AtlasTypeDefStore typeDefStore;
+
+    AtlasEntityStore entityStore;
+
+    @Inject
+    DeleteHandlerV1 deleteHandler;
+
+    private AtlasEntitiesWithExtInfo deptEntity;
+    private AtlasEntityWithExtInfo   dbEntity;
+    private AtlasEntityWithExtInfo   tblEntity;
+    private AtlasEntityWithExtInfo   primitiveEntity;
+
+    AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class);
+    @Inject
+    private EntityGraphMapper graphMapper;
+
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        RequestContextV1.clear();
+        RequestContextV1.get().setUser(TestUtilsV2.TEST_USER);
+
+        new GraphBackedSearchIndexer(typeRegistry);
+
+        AtlasTypesDef[] testTypesDefs = new AtlasTypesDef[] { TestUtilsV2.defineDeptEmployeeTypes(),
+                                                              TestUtilsV2.defineHiveTypes()
+                                                            };
+
+        for (AtlasTypesDef typesDef : testTypesDefs) {
+            AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(typesDef, typeRegistry);
+
+            if (!typesToCreate.isEmpty()) {
+                typeDefStore.createTypesDef(typesToCreate);
+            }
+        }
+
+        deptEntity = TestUtilsV2.createDeptEg2();
+        dbEntity   = TestUtilsV2.createDBEntityV2();
+        tblEntity  = TestUtilsV2.createTableEntityV2(dbEntity.getEntity());
+
+        AtlasTypesDef typesDef11 = new  AtlasTypesDef();
+        List primitiveEntityDef = new ArrayList<AtlasEntityDef>();
+        primitiveEntityDef.add(TestUtilsV2.createPrimitiveEntityDef());
+        typesDef11.setEntityDefs(primitiveEntityDef);
+        typeDefStore.createTypesDef( typesDef11 );
+
+        primitiveEntity = TestUtilsV2.createprimitiveEntityV2();
+    }
+
+    @AfterClass
+    public void clear() {
+        AtlasGraphProvider.cleanup();
+    }
+
+    @BeforeTest
+    public void init() throws Exception {
+        entityStore = new AtlasEntityStoreV1(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper);
+        RequestContextV1.clear();
+        RequestContextV1.get().setUser(TestUtilsV2.TEST_USER);
+    }
+
+    @Test
+    public void testDefaultValueForPrimitiveTypes() throws Exception  {
+
+        init();
+
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(primitiveEntity), false);
+        List<AtlasEntityHeader> entitiesCreatedResponse = response.getEntitiesByOperation(EntityOperation.CREATE);
+        final Map<EntityOperation, List<AtlasEntityHeader>> entitiesMutated = response.getMutatedEntities();
+        List<AtlasEntityHeader> entitiesCreatedwithdefault = entitiesMutated.get(EntityOperation.CREATE);
+
+        AtlasEntity entityCreated   = getEntityFromStore(entitiesCreatedResponse.get(0));
+
+
+        Map attributesMap = entityCreated.getAttributes();
+        String description = (String) attributesMap.get("description");
+        String check = (String) attributesMap.get("check");
+        String   sourceCode =  (String) attributesMap.get("sourcecode");
+        float   diskUsage =  (float) attributesMap.get("diskUsage");
+        boolean   isstoreUse =  (boolean) attributesMap.get("isstoreUse");
+        int cost = (int)attributesMap.get("Cost");
+
+
+        assertEquals(description,"test");
+        assertEquals(check,"check");
+
+        //defaultValue
+        assertEquals(diskUsage,70.5f);
+        assertEquals(isstoreUse,true);
+        assertEquals(sourceCode,"Hello World");
+        assertEquals(cost,30);
+    }
+
+
+    @Test
+    public void testCreate() throws Exception {
+        init();
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(deptEntity), false);
+
+        validateMutationResponse(response, EntityOperation.CREATE, 5);
+        AtlasEntityHeader dept1 = response.getFirstCreatedEntityByTypeName(TestUtilsV2.DEPARTMENT_TYPE);
+        validateEntity(deptEntity, getEntityFromStore(dept1), deptEntity.getEntities().get(0));
+
+        final Map<EntityOperation, List<AtlasEntityHeader>> entitiesMutated = response.getMutatedEntities();
+        List<AtlasEntityHeader> entitiesCreated = entitiesMutated.get(EntityOperation.CREATE);
+
+        Assert.assertTrue(entitiesCreated.size() >= deptEntity.getEntities().size());
+
+        for (int i = 0; i < deptEntity.getEntities().size(); i++) {
+            AtlasEntity expected = deptEntity.getEntities().get(i);
+            AtlasEntity actual   = getEntityFromStore(entitiesCreated.get(i));
+
+            validateEntity(deptEntity, actual, expected);
+        }
+
+        //Create DB
+        init();
+        EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
+        validateMutationResponse(dbCreationResponse, EntityOperation.CREATE, 1);
+
+        AtlasEntityHeader db1 = dbCreationResponse.getFirstCreatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE);
+        validateEntity(dbEntity, getEntityFromStore(db1));
+
+        //Create Table
+        //Update DB guid
+        AtlasObjectId dbObjectId = (AtlasObjectId) tblEntity.getEntity().getAttribute("database");
+        dbObjectId.setGuid(db1.getGuid());
+        tblEntity.addReferredEntity(dbEntity.getEntity());
+
+        init();
+        EntityMutationResponse tableCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(tblEntity), false);
+        validateMutationResponse(tableCreationResponse, EntityOperation.CREATE, 1);
+
+        AtlasEntityHeader tableEntity = tableCreationResponse.getFirstCreatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(tblEntity, getEntityFromStore(tableEntity));
+    }
+
+    @Test(dependsOnMethods = "testCreate")
+    public void testArrayOfEntityUpdate() throws Exception {
+        AtlasEntity              tableEntity  = new AtlasEntity(tblEntity.getEntity());
+        List<AtlasObjectId>      columns      = new ArrayList<>();
+        AtlasEntitiesWithExtInfo entitiesInfo = new AtlasEntitiesWithExtInfo(tableEntity);
+
+
+        AtlasEntity col1 = TestUtilsV2.createColumnEntity(tableEntity);
+        col1.setAttribute(TestUtilsV2.NAME, "col1");
+
+        AtlasEntity col2 = TestUtilsV2.createColumnEntity(tableEntity);
+        col2.setAttribute(TestUtilsV2.NAME, "col2");
+
+        columns.add(AtlasTypeUtil.getAtlasObjectId(col1));
+        columns.add(AtlasTypeUtil.getAtlasObjectId(col2));
+
+        tableEntity.setAttribute(TestUtilsV2.COLUMNS_ATTR_NAME, columns);
+
+        entitiesInfo.addReferredEntity(dbEntity.getEntity());
+        entitiesInfo.addReferredEntity(col1);
+        entitiesInfo.addReferredEntity(col2);
+
+        init();
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+
+        AtlasEntityHeader updatedTableHeader = response.getFirstUpdatedEntityByTypeName(tableEntity.getTypeName());
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTableHeader));
+
+        //Complete update. Add  array elements - col3,col4
+        AtlasEntity col3 = TestUtilsV2.createColumnEntity(tableEntity);
+        col3.setAttribute(TestUtilsV2.NAME, "col3");
+
+        AtlasEntity col4 = TestUtilsV2.createColumnEntity(tableEntity);
+        col4.setAttribute(TestUtilsV2.NAME, "col4");
+
+        columns.add(AtlasTypeUtil.getAtlasObjectId(col3));
+        columns.add(AtlasTypeUtil.getAtlasObjectId(col4));
+        tableEntity.setAttribute(TestUtilsV2.COLUMNS_ATTR_NAME, columns);
+
+        entitiesInfo.addReferredEntity(col3);
+        entitiesInfo.addReferredEntity(col4);
+
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+
+        updatedTableHeader = response.getFirstUpdatedEntityByTypeName(tableEntity.getTypeName());
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTableHeader));
+
+        //Swap elements
+        columns.clear();
+        columns.add(AtlasTypeUtil.getAtlasObjectId(col4));
+        columns.add(AtlasTypeUtil.getAtlasObjectId(col3));
+        tableEntity.setAttribute(TestUtilsV2.COLUMNS_ATTR_NAME, columns);
+
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+
+        updatedTableHeader = response.getFirstUpdatedEntityByTypeName(tableEntity.getTypeName());
+        AtlasEntity updatedEntity = getEntityFromStore(updatedTableHeader);
+        // deleted columns are also included in "columns" attribute
+        Assert.assertTrue(((List<AtlasObjectId>) updatedEntity.getAttribute(COLUMNS_ATTR_NAME)).size() >= 2);
+
+        assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE).size(), 2);  // col1, col2 are deleted
+
+        //Update array column to null
+        tableEntity.setAttribute(COLUMNS_ATTR_NAME, null);
+
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+
+        updatedTableHeader = response.getFirstUpdatedEntityByTypeName(tableEntity.getTypeName());
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTableHeader));
+        assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE).size(), 2);
+    }
+
+    @Test(dependsOnMethods = "testCreate")
+    public void testUpdateEntityWithMap() throws Exception {
+        AtlasEntity              tableEntity  = new AtlasEntity(tblEntity.getEntity());
+        AtlasEntitiesWithExtInfo entitiesInfo = new AtlasEntitiesWithExtInfo(tableEntity);
+        Map<String, AtlasStruct> partsMap     = new HashMap<>();
+        partsMap.put("part0", new AtlasStruct(TestUtilsV2.PARTITION_STRUCT_TYPE, TestUtilsV2.NAME, "test"));
+
+        tableEntity.setAttribute("partitionsMap", partsMap);
+
+        init();
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+
+        AtlasEntityHeader tableDefinition1 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        AtlasEntity updatedTableDef1 = getEntityFromStore(tableDefinition1);
+        validateEntity(entitiesInfo, updatedTableDef1);
+                
+        Assert.assertTrue(partsMap.get("part0").equals(((Map<String, AtlasStruct>) updatedTableDef1.getAttribute("partitionsMap")).get("part0")));
+
+        //update map - add a map key
+        partsMap.put("part1", new AtlasStruct(TestUtilsV2.PARTITION_STRUCT_TYPE, TestUtilsV2.NAME, "test1"));
+        tableEntity.setAttribute("partitionsMap", partsMap);
+
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+
+        AtlasEntityHeader tableDefinition2 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        AtlasEntity updatedTableDef2 = getEntityFromStore(tableDefinition2);
+        validateEntity(entitiesInfo, updatedTableDef2);
+
+        assertEquals(((Map<String, AtlasStruct>) updatedTableDef2.getAttribute("partitionsMap")).size(), 2);
+        Assert.assertTrue(partsMap.get("part1").equals(((Map<String, AtlasStruct>) updatedTableDef2.getAttribute("partitionsMap")).get("part1")));
+
+        //update map - remove a key and add another key
+        partsMap.remove("part0");
+        partsMap.put("part2", new AtlasStruct(TestUtilsV2.PARTITION_STRUCT_TYPE, TestUtilsV2.NAME, "test2"));
+        tableEntity.setAttribute("partitionsMap", partsMap);
+
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+
+        AtlasEntityHeader tableDefinition3 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        AtlasEntity updatedTableDef3 = getEntityFromStore(tableDefinition3);
+        validateEntity(entitiesInfo, updatedTableDef3);
+
+        assertEquals(((Map<String, AtlasStruct>) updatedTableDef3.getAttribute("partitionsMap")).size(), 2);
+        Assert.assertNull(((Map<String, AtlasStruct>) updatedTableDef3.getAttribute("partitionsMap")).get("part0"));
+        Assert.assertTrue(partsMap.get("part2").equals(((Map<String, AtlasStruct>) updatedTableDef3.getAttribute("partitionsMap")).get("part2")));
+
+        //update struct value for existing map key
+        AtlasStruct partition2 = partsMap.get("part2");
+        partition2.setAttribute(TestUtilsV2.NAME, "test2Updated");
+
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+
+        AtlasEntityHeader tableDefinition4 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        AtlasEntity updatedTableDef4 = getEntityFromStore(tableDefinition4);
+        validateEntity(entitiesInfo, updatedTableDef4);
+
+        assertEquals(((Map<String, AtlasStruct>) updatedTableDef4.getAttribute("partitionsMap")).size(), 2);
+        Assert.assertNull(((Map<String, AtlasStruct>) updatedTableDef4.getAttribute("partitionsMap")).get("part0"));
+        Assert.assertTrue(partsMap.get("part2").equals(((Map<String, AtlasStruct>) updatedTableDef4.getAttribute("partitionsMap")).get("part2")));
+
+        //Test map pointing to a class
+
+        AtlasEntity col0 = new AtlasEntity(TestUtilsV2.COLUMN_TYPE, TestUtilsV2.NAME, "test1");
+        col0.setAttribute("type", "string");
+        col0.setAttribute("table", AtlasTypeUtil.getAtlasObjectId(tableEntity));
+
+        AtlasEntityWithExtInfo col0WithExtendedInfo = new AtlasEntityWithExtInfo(col0);
+        col0WithExtendedInfo.addReferredEntity(tableEntity);
+        col0WithExtendedInfo.addReferredEntity(dbEntity.getEntity());
+
+        init();
+        entityStore.createOrUpdate(new AtlasEntityStream(col0WithExtendedInfo), false);
+
+        AtlasEntity col1 = new AtlasEntity(TestUtilsV2.COLUMN_TYPE, TestUtilsV2.NAME, "test2");
+        col1.setAttribute("type", "string");
+        col1.setAttribute("table", AtlasTypeUtil.getAtlasObjectId(tableEntity));
+
+        AtlasEntityWithExtInfo col1WithExtendedInfo = new AtlasEntityWithExtInfo(col1);
+        col1WithExtendedInfo.addReferredEntity(tableEntity);
+        col1WithExtendedInfo.addReferredEntity(dbEntity.getEntity());
+
+        init();
+        entityStore.createOrUpdate(new AtlasEntityStream(col1WithExtendedInfo), false);
+
+        Map<String, AtlasObjectId> columnsMap = new HashMap<String, AtlasObjectId>();
+        columnsMap.put("col0", AtlasTypeUtil.getAtlasObjectId(col0));
+        columnsMap.put("col1", AtlasTypeUtil.getAtlasObjectId(col1));
+
+        tableEntity.setAttribute(TestUtilsV2.COLUMNS_MAP, columnsMap);
+
+        entitiesInfo.addReferredEntity(col0);
+        entitiesInfo.addReferredEntity(col1);
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        AtlasEntityHeader tableDefinition5 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(tableDefinition5));
+
+        //Swap elements
+        columnsMap.clear();
+        columnsMap.put("col0", AtlasTypeUtil.getAtlasObjectId(col1));
+        columnsMap.put("col1", AtlasTypeUtil.getAtlasObjectId(col0));
+
+        tableEntity.setAttribute(TestUtilsV2.COLUMNS_MAP, columnsMap);
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        AtlasEntityHeader tableDefinition6 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(tableDefinition6));
+
+        Assert.assertEquals(entityStore.getById(col0.getGuid()).getEntity().getStatus(), AtlasEntity.Status.ACTIVE);
+        Assert.assertEquals(entityStore.getById(col1.getGuid()).getEntity().getStatus(), AtlasEntity.Status.ACTIVE);
+
+        //Drop the first key and change the class type as well to col0
+        columnsMap.clear();
+        columnsMap.put("col0", AtlasTypeUtil.getAtlasObjectId(col0));
+        init();
+
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        AtlasEntityHeader tableDefinition7 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(tableDefinition7));
+
+        //Clear state
+        tableEntity.setAttribute(TestUtilsV2.COLUMNS_MAP, null);
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        AtlasEntityHeader tableDefinition8 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(tableDefinition8));
+    }
+
+    @Test(dependsOnMethods = "testCreate")
+    public void testMapOfPrimitivesUpdate() throws Exception {
+        AtlasEntity              tableEntity  = new AtlasEntity(tblEntity.getEntity());
+        AtlasEntitiesWithExtInfo entitiesInfo = new AtlasEntitiesWithExtInfo(tableEntity);
+
+        entitiesInfo.addReferredEntity(tableEntity);
+
+        //Add a new entry
+        Map<String, String> paramsMap = (Map<String, String>) tableEntity.getAttribute("parametersMap");
+        paramsMap.put("newParam", "value");
+        init();
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 1);
+        AtlasEntityHeader updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
+
+        //Remove an entry
+        paramsMap.remove("key1");
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 1);
+        updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
+    }
+
+    @Test(dependsOnMethods = "testCreate")
+    public void testArrayOfStructs() throws Exception {
+        //Modify array of structs
+        AtlasEntity              tableEntity  = new AtlasEntity(tblEntity.getEntity());
+        AtlasEntitiesWithExtInfo entitiesInfo = new AtlasEntitiesWithExtInfo(tableEntity);
+
+        List<AtlasStruct> partitions = new ArrayList<AtlasStruct>(){{
+            add(new AtlasStruct(TestUtilsV2.PARTITION_STRUCT_TYPE, TestUtilsV2.NAME, "part1"));
+            add(new AtlasStruct(TestUtilsV2.PARTITION_STRUCT_TYPE, TestUtilsV2.NAME, "part2"));
+        }};
+        tableEntity.setAttribute("partitions", partitions);
+
+        init();
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        AtlasEntityHeader updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
+
+        //add a new element to array of struct
+        partitions.add(new AtlasStruct(TestUtilsV2.PARTITION_STRUCT_TYPE, TestUtilsV2.NAME, "part3"));
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
+
+        //remove one of the struct values
+        init();
+        partitions.remove(1);
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
+
+        //Update struct value within array of struct
+        init();
+        partitions.get(0).setAttribute(TestUtilsV2.NAME, "part4");
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
+
+
+        //add a repeated element to array of struct
+        partitions.add(new AtlasStruct(TestUtilsV2.PARTITION_STRUCT_TYPE, TestUtilsV2.NAME, "part4"));
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
+
+        // Remove all elements. Should set array attribute to null
+        partitions.clear();
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
+    }
+
+
+    @Test(dependsOnMethods = "testCreate")
+    public void testStructs() throws Exception {
+        AtlasEntity              databaseEntity = dbEntity.getEntity();
+        AtlasEntity              tableEntity    = new AtlasEntity(tblEntity.getEntity());
+        AtlasEntitiesWithExtInfo entitiesInfo   = new AtlasEntitiesWithExtInfo(tableEntity);
+
+        AtlasStruct serdeInstance = new AtlasStruct(TestUtilsV2.SERDE_TYPE, TestUtilsV2.NAME, "serde1Name");
+        serdeInstance.setAttribute("serde", "test");
+        serdeInstance.setAttribute("description", "testDesc");
+        tableEntity.setAttribute("serde1", serdeInstance);
+        tableEntity.setAttribute("database", new AtlasObjectId(databaseEntity.getTypeName(), TestUtilsV2.NAME, databaseEntity.getAttribute(TestUtilsV2.NAME)));
+
+        init();
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        AtlasEntityHeader updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
+
+        //update struct attribute
+        serdeInstance.setAttribute("serde", "testUpdated");
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
+
+        //set to null
+        tableEntity.setAttribute("description", null);
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        Assert.assertNull(updatedTable.getAttribute("description"));
+        validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
+    }
+
+    @Test(dependsOnMethods = "testCreate")
+    public void testClassUpdate() throws Exception {
+
+        init();
+        //Create new db instance
+        final AtlasEntity databaseInstance = TestUtilsV2.createDBEntity();
+
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(databaseInstance), false);
+        final AtlasEntityHeader dbCreated = response.getFirstCreatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE);
+
+        init();
+        Map<String, AtlasEntity> tableCloneMap = new HashMap<>();
+        AtlasEntity tableClone = new AtlasEntity(tblEntity.getEntity());
+        tableClone.setAttribute("database", new AtlasObjectId(dbCreated.getGuid(), TestUtilsV2.DATABASE_TYPE));
+
+        tableCloneMap.put(dbCreated.getGuid(), databaseInstance);
+        tableCloneMap.put(tableClone.getGuid(), tableClone);
+
+        response = entityStore.createOrUpdate(new InMemoryMapEntityStream(tableCloneMap), false);
+        final AtlasEntityHeader tableDefinition = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
+        AtlasEntity updatedTableDefinition = getEntityFromStore(tableDefinition);
+        Assert.assertNotNull(updatedTableDefinition.getAttribute("database"));
+        Assert.assertEquals(((AtlasObjectId) updatedTableDefinition.getAttribute("database")).getGuid(), dbCreated.getGuid());
+    }
+
+    @Test
+    public void testCheckOptionalAttrValueRetention() throws Exception {
+
+        AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
+
+        init();
+        EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
+        AtlasEntity firstEntityCreated = getEntityFromStore(response.getFirstCreatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE));
+
+        //The optional boolean attribute should have a non-null value
+        final String isReplicatedAttr = "isReplicated";
+        final String paramsAttr = "parameters";
+        Assert.assertNotNull(firstEntityCreated.getAttribute(isReplicatedAttr));
+        Assert.assertEquals(firstEntityCreated.getAttribute(isReplicatedAttr), Boolean.FALSE);
+        Assert.assertNull(firstEntityCreated.getAttribute(paramsAttr));
+
+        //Update to true
+        dbEntity.setAttribute(isReplicatedAttr, Boolean.TRUE);
+        //Update array
+        final HashMap<String, String> params = new HashMap<String, String>() {{ put("param1", "val1"); put("param2", "val2"); }};
+        dbEntity.setAttribute(paramsAttr, params);
+        //Complete update
+
+        init();
+        response = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
+        AtlasEntity firstEntityUpdated = getEntityFromStore(response.getFirstUpdatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE));
+
+        Assert.assertNotNull(firstEntityUpdated);
+        Assert.assertNotNull(firstEntityUpdated.getAttribute(isReplicatedAttr));
+        Assert.assertEquals(firstEntityUpdated.getAttribute(isReplicatedAttr), Boolean.TRUE);
+        Assert.assertEquals(firstEntityUpdated.getAttribute(paramsAttr), params);
+
+        //TODO - enable test after GET API is ready
+//        init();
+//        //Complete update without setting the attribute
+//        AtlasEntity newEntity = TestUtilsV2.createDBEntity();
+//        //Reset name to the current DB name
+//        newEntity.setAttribute(AtlasClient.NAME, firstEntityCreated.getAttribute(AtlasClient.NAME));
+//        response = entityStore.createOrUpdate(newEntity);
+//
+//        firstEntityUpdated = response.getFirstEntityUpdated();
+//        Assert.assertNotNull(firstEntityUpdated.getAttribute(isReplicatedAttr));
+//        Assert.assertEquals(firstEntityUpdated.getAttribute(isReplicatedAttr), Boolean.TRUE);
+//        Assert.assertEquals(firstEntityUpdated.getAttribute(paramsAttr), params);
+    }
+
+    @Test(enabled = false)
+    //Titan doesn't allow some reserved chars in property keys. Verify that atlas encodes these
+    //See GraphHelper.encodePropertyKey()
+    //TODO : Failing in typedef creation
+    public void testSpecialCharacters() throws Exception {
+        //Verify that type can be created with reserved characters in typename, attribute name
+        final String typeName = TestUtilsV2.randomString(10);
+        String strAttrName = randomStrWithReservedChars();
+        String arrayAttrName = randomStrWithReservedChars();
+        String mapAttrName = randomStrWithReservedChars();
+
+        AtlasEntityDef typeDefinition =
+            AtlasTypeUtil.createClassTypeDef(typeName, "Special chars test type", ImmutableSet.<String>of(),
+                AtlasTypeUtil.createOptionalAttrDef(strAttrName, "string"),
+                AtlasTypeUtil.createOptionalAttrDef(arrayAttrName, "array<string>"),
+                AtlasTypeUtil.createOptionalAttrDef(mapAttrName, "map<string,string>"));
+
+        AtlasTypesDef atlasTypesDef = new AtlasTypesDef(null, null, null, Arrays.asList(typeDefinition));
+        typeDefStore.createTypesDef(atlasTypesDef);
+
+        //verify that entity can be created with reserved characters in string value, array value and map key and value
+        AtlasEntity entity = new AtlasEntity();
+        entity.setAttribute(strAttrName, randomStrWithReservedChars());
+        entity.setAttribute(arrayAttrName, new String[]{randomStrWithReservedChars()});
+        entity.setAttribute(mapAttrName, new HashMap<String, String>() {{
+            put(randomStrWithReservedChars(), randomStrWithReservedChars());
+        }});
+
+        AtlasEntityWithExtInfo entityWithExtInfo = new AtlasEntityWithExtInfo(entity);
+
+        final EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entityWithExtInfo), false);
+        final AtlasEntityHeader firstEntityCreated = response.getFirstEntityCreated();
+        validateEntity(entityWithExtInfo, getEntityFromStore(firstEntityCreated));
+
+
+        //Verify that search with reserved characters works - for string attribute
+//        String query =
+//            String.format("`%s` where `%s` = '%s'", typeName, strAttrName, entity.getAttribute(strAttrName));
+//        String responseJson = discoveryService.searchByDSL(query, new QueryParams(1, 0));
+//        JSONObject response = new JSONObject(responseJson);
+//        assertEquals(response.getJSONArray("rows").length(), 1);
+    }
+
+    @Test(expectedExceptions = AtlasBaseException.class)
+    public void testCreateRequiredAttrNull() throws Exception {
+        //Update required attribute
+        Map<String, AtlasEntity> tableCloneMap = new HashMap<>();
+        AtlasEntity tableEntity = new AtlasEntity(TABLE_TYPE);
+        tableEntity.setAttribute(TestUtilsV2.NAME, "table_" + TestUtilsV2.randomString());
+        tableCloneMap.put(tableEntity.getGuid(), tableEntity);
+
+        entityStore.createOrUpdate(new InMemoryMapEntityStream(tableCloneMap), false);
+        Assert.fail("Expected exception while creating with required attribute null");
+    }
+
+    @Test
+    public void testPartialUpdateAttr() throws Exception {
+        //Update optional attribute
+
+        init();
+
+        AtlasEntity dbEntity = new AtlasEntity(TestUtilsV2.DATABASE_TYPE);
+        dbEntity.setAttribute("name", TestUtilsV2.randomString(10));
+        dbEntity.setAttribute("description", "us db");
+        dbEntity.setAttribute("isReplicated", false);
+        dbEntity.setAttribute("created", "09081988");
+        dbEntity.setAttribute("namespace", "db namespace");
+        dbEntity.setAttribute("cluster", "Fenton_Cluster");
+        dbEntity.setAttribute("colo", "10001");
+
+        EntityStream           dbStream        = new AtlasEntityStream(new AtlasEntitiesWithExtInfo(dbEntity));
+        EntityMutationResponse response        = entityStore.createOrUpdate(dbStream, false);
+        AtlasEntityHeader      dbHeader        = response.getFirstEntityCreated();
+        AtlasEntity            createdDbEntity = getEntityFromStore(dbHeader);
+
+        // update the db entity
+        dbEntity = new AtlasEntity(TestUtilsV2.DATABASE_TYPE);
+        dbEntity.setGuid(createdDbEntity.getGuid());
+        // dbEntity.setAttribute("name", createdDbEntity.getAttribute("name"));
+        // dbEntity.setAttribute("description", "another db"); // required attr
+        dbEntity.setAttribute("created", "08151947");       // optional attr
+        dbEntity.setAttribute("isReplicated", true);       // optional attr
+
+        dbStream = new AtlasEntityStream(new AtlasEntitiesWithExtInfo(dbEntity));
+
+        // fail full update if required attributes are not specified.
+        try {
+            entityStore.createOrUpdate(dbStream, false);
+        } catch (AtlasBaseException ex) {
+            Assert.assertEquals(ex.getAtlasErrorCode(), AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS);
+        }
+
+        // do partial update without providing required attributes
+        dbStream.reset();
+        response = entityStore.createOrUpdate(dbStream, true);
+        dbHeader = response.getFirstEntityPartialUpdated();
+        AtlasEntity updatedDbEntity = getEntityFromStore(dbHeader);
+
+        assertEquals(updatedDbEntity.getAttribute("name"), createdDbEntity.getAttribute("name"));
+        assertEquals(updatedDbEntity.getAttribute("description"), createdDbEntity.getAttribute("description"));
+        assertEquals(updatedDbEntity.getAttribute("isReplicated"), true);
+        assertEquals(updatedDbEntity.getAttribute("created"), "08151947");
+        assertEquals(updatedDbEntity.getAttribute("namespace"), createdDbEntity.getAttribute("namespace"));
+        assertEquals(updatedDbEntity.getAttribute("cluster"), createdDbEntity.getAttribute("cluster"));
+        assertEquals(updatedDbEntity.getAttribute("colo"), createdDbEntity.getAttribute("colo"));
+
+        // create a new table type
+        AtlasEntity tblEntity = new AtlasEntity(TABLE_TYPE);
+        tblEntity.setAttribute("name", TestUtilsV2.randomString(10));
+        tblEntity.setAttribute("type", "type");
+        tblEntity.setAttribute("tableType", "MANAGED");
+        tblEntity.setAttribute("database", AtlasTypeUtil.getAtlasObjectId(updatedDbEntity));
+
+        // create new column entity
+        AtlasEntity col1 = TestUtilsV2.createColumnEntity(tblEntity);
+        AtlasEntity col2 = TestUtilsV2.createColumnEntity(tblEntity);
+        col1.setAttribute(TestUtilsV2.NAME, "col1");
+        col2.setAttribute(TestUtilsV2.NAME, "col2");
+
+        List<AtlasObjectId> columns = new ArrayList<>();
+        columns.add(AtlasTypeUtil.getAtlasObjectId(col1));
+        columns.add(AtlasTypeUtil.getAtlasObjectId(col2));
+
+        tblEntity.setAttribute(TestUtilsV2.COLUMNS_ATTR_NAME, columns);
+
+        AtlasEntitiesWithExtInfo tableEntityInfo = new AtlasEntitiesWithExtInfo(tblEntity);
+        tableEntityInfo.addReferredEntity(col1.getGuid(), col1);
+        tableEntityInfo.addReferredEntity(col2.getGuid(), col2);
+
+        EntityStream tblStream = new AtlasEntityStream(tableEntityInfo);
+        response = entityStore.createOrUpdate(tblStream, false);
+        AtlasEntityHeader tblHeader = response.getFirstEntityCreated();
+        AtlasEntity createdTblEntity = getEntityFromStore(tblHeader);
+
+        columns = (List<AtlasObjectId>) createdTblEntity.getAttribute(TestUtilsV2.COLUMNS_ATTR_NAME);
+        assertEquals(columns.size(), 2);
+
+        // update - add 2 more columns to table
+        AtlasEntity col3 = TestUtilsV2.createColumnEntity(createdTblEntity);
+        col3.setAttribute(TestUtilsV2.NAME, "col3");
+        col3.setAttribute("description", "description col3");
+
+        AtlasEntity col4 = TestUtilsV2.createColumnEntity(createdTblEntity);
+        col4.setAttribute(TestUtilsV2.NAME, "col4");
+        col4.setAttribute("description", "description col4");
+
+        columns.clear();
+        columns.add(AtlasTypeUtil.getAtlasObjectId(col3));
+        columns.add(AtlasTypeUtil.getAtlasObjectId(col4));
+
+        tblEntity = new AtlasEntity(TABLE_TYPE);
+        tblEntity.setGuid(createdTblEntity.getGuid());
+        tblEntity.setAttribute(TestUtilsV2.COLUMNS_ATTR_NAME, columns);
+
+        tableEntityInfo = new AtlasEntitiesWithExtInfo(tblEntity);
+        tableEntityInfo.addReferredEntity(col3.getGuid(), col3);
+        tableEntityInfo.addReferredEntity(col4.getGuid(), col4);
+
+        tblStream = new AtlasEntityStream(tableEntityInfo);
+        response  = entityStore.createOrUpdate(tblStream, true);
+        tblHeader = response.getFirstEntityPartialUpdated();
+        AtlasEntity updatedTblEntity = getEntityFromStore(tblHeader);
+
+        columns = (List<AtlasObjectId>) updatedTblEntity.getAttribute(TestUtilsV2.COLUMNS_ATTR_NAME);
+        // deleted columns are included in the attribute; hence use >=
+        assertTrue(columns.size() >= 2);
+    }
+
+    @Test
+    public void testPartialUpdateArrayAttr() throws Exception {
+        // Create a table entity, with 3 reference column entities
+        init();
+        final AtlasEntity      dbEntity           = TestUtilsV2.createDBEntity();
+        EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
+
+        final AtlasEntity        tableEntity      = TestUtilsV2.createTableEntity(dbEntity);
+        AtlasEntitiesWithExtInfo entitiesInfo     = new AtlasEntitiesWithExtInfo(tableEntity);
+
+        final AtlasEntity columnEntity1 = TestUtilsV2.createColumnEntity(tableEntity);
+        columnEntity1.setAttribute("description", "desc for col1");
+        entitiesInfo.addReferredEntity(columnEntity1);
+
+        final AtlasEntity columnEntity2 = TestUtilsV2.createColumnEntity(tableEntity);
+        columnEntity2.setAttribute("description", "desc for col2");
+        entitiesInfo.addReferredEntity(columnEntity2);
+
+        final AtlasEntity columnEntity3 = TestUtilsV2.createColumnEntity(tableEntity);
+        columnEntity3.setAttribute("description", "desc for col3");
+        entitiesInfo.addReferredEntity(columnEntity3);
+
+        tableEntity.setAttribute(COLUMNS_ATTR_NAME, Arrays.asList(AtlasTypeUtil.getAtlasObjectId(columnEntity1),
+                                                                  AtlasTypeUtil.getAtlasObjectId(columnEntity2),
+                                                                  AtlasTypeUtil.getAtlasObjectId(columnEntity3)));
+
+        init();
+
+        final EntityMutationResponse tblCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
+        final AtlasEntityHeader      createdTblHeader    = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(TABLE_TYPE, NAME, (String) tableEntity.getAttribute(NAME));
+        final AtlasEntity            createdTblEntity    = getEntityFromStore(createdTblHeader);
+
+        final AtlasEntityHeader column1Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity1.getAttribute(NAME));
+        final AtlasEntityHeader column2Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity2.getAttribute(NAME));
+        final AtlasEntityHeader column3Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity3.getAttribute(NAME));
+
+        // update only description attribute of all 3 columns
+        AtlasEntity col1 = new AtlasEntity(COLUMN_TYPE);
+        col1.setGuid(column1Created.getGuid());
+        col1.setAttribute("description", "desc for col1:updated");
+
+        AtlasEntity col2 = new AtlasEntity(COLUMN_TYPE);
+        col2.setGuid(column2Created.getGuid());
+        col2.setAttribute("description", "desc for col2:updated");
+
+        AtlasEntity col3 = new AtlasEntity(COLUMN_TYPE);
+        col3.setGuid(column3Created.getGuid());
+        col3.setAttribute("description", "desc for col3:updated");
+
+        final AtlasEntity tableEntity1 = new AtlasEntity(TABLE_TYPE);
+        tableEntity1.setGuid(createdTblHeader.getGuid());
+        tableEntity1.setAttribute(COLUMNS_ATTR_NAME, Arrays.asList(AtlasTypeUtil.getAtlasObjectId(col1),
+                AtlasTypeUtil.getAtlasObjectId(col2),
+                AtlasTypeUtil.getAtlasObjectId(col3)));
+        AtlasEntitiesWithExtInfo tableInfo = new AtlasEntitiesWithExtInfo(tableEntity1);
+        tableInfo.addReferredEntity(col1.getGuid(), col1);
+        tableInfo.addReferredEntity(col2.getGuid(), col2);
+        tableInfo.addReferredEntity(col3.getGuid(), col3);
+
+        init();
+
+        final EntityMutationResponse tblUpdateResponse = entityStore.createOrUpdate(new AtlasEntityStream(tableInfo), true);
+        final AtlasEntityHeader      updatedTblHeader  = tblUpdateResponse.getFirstEntityPartialUpdated();
+        final AtlasEntity            updatedTblEntity2 = getEntityFromStore(updatedTblHeader);
+        List<AtlasEntityHeader>      updatedColHeaders = tblUpdateResponse.getPartialUpdatedEntitiesByTypeName(COLUMN_TYPE);
+
+        final AtlasEntity updatedCol1Entity = getEntityFromStore(updatedColHeaders.get(0));
+        final AtlasEntity updatedCol2Entity = getEntityFromStore(updatedColHeaders.get(1));
+        final AtlasEntity updatedCol3Entity = getEntityFromStore(updatedColHeaders.get(2));
+
+        assertEquals(col1.getAttribute("description"), updatedCol1Entity.getAttribute("description"));
+        assertEquals(col2.getAttribute("description"), updatedCol2Entity.getAttribute("description"));
+        assertEquals(col3.getAttribute("description"), updatedCol3Entity.getAttribute("description"));
+    }
+
+    @Test
+    public void testSetObjectIdAttrToNull() throws Exception {
+        final AtlasEntity dbEntity  = TestUtilsV2.createDBEntity();
+        final AtlasEntity db2Entity = TestUtilsV2.createDBEntity();
+
+        entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
+        entityStore.createOrUpdate(new AtlasEntityStream(db2Entity), false);
+
+        final AtlasEntity tableEntity = TestUtilsV2.createTableEntity(dbEntity);
+
+        tableEntity.setAttribute("databaseComposite", AtlasTypeUtil.getAtlasObjectId(db2Entity));
+
+        final EntityMutationResponse tblCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(tableEntity), false);
+        final AtlasEntityHeader      createdTblHeader    = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(TABLE_TYPE, NAME, (String) tableEntity.getAttribute(NAME));
+        final AtlasEntity            createdTblEntity    = getEntityFromStore(createdTblHeader);
+
+        init();
+
+        createdTblEntity.setAttribute("databaseComposite", null);
+
+        final EntityMutationResponse tblUpdateResponse = entityStore.createOrUpdate(new AtlasEntityStream(createdTblEntity), true);
+        final AtlasEntityHeader      updatedTblHeader  = tblUpdateResponse.getFirstEntityPartialUpdated();
+        final AtlasEntity            updatedTblEntity  = getEntityFromStore(updatedTblHeader);
+        final AtlasEntity            deletedDb2Entity  = getEntityFromStore(db2Entity.getGuid());
+
+        assertEquals(deletedDb2Entity.getStatus(), AtlasEntity.Status.DELETED);
+    }
+
+    @Test
+    public void testTagAssociationAfterRedefinition(){
+        AtlasClassificationDef aTag = new AtlasClassificationDef("testTag");
+        AtlasAttributeDef attributeDef = new AtlasAttributeDef("testAttribute", "int", true,
+                AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+                false, true,
+                Collections.<AtlasStructDef.AtlasConstraintDef>emptyList());
+        aTag.addAttribute(attributeDef);
+
+        AtlasTypesDef typesDef = new AtlasTypesDef();
+        typesDef.setClassificationDefs(Arrays.asList(aTag));
+
+        try {
+            typeDefStore.createTypesDef(typesDef);
+        } catch (AtlasBaseException e) {
+            fail("Tag creation should've succeeded");
+        }
+
+        try {
+            typeDefStore.deleteTypesDef(typesDef);
+        } catch (AtlasBaseException e) {
+            fail("Tag deletion should've succeeded");
+        }
+
+        aTag = new AtlasClassificationDef("testTag");
+        attributeDef = new AtlasAttributeDef("testAttribute", "string", true,
+                AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+                false, true,
+                Collections.<AtlasStructDef.AtlasConstraintDef>emptyList());
+        aTag.addAttribute(attributeDef);
+        typesDef.setClassificationDefs(Arrays.asList(aTag));
+
+        try {
+            typeDefStore.createTypesDef(typesDef);
+        } catch (AtlasBaseException e) {
+            fail("Tag re-creation should've succeeded");
+        }
+
+        final AtlasEntity dbEntity  = TestUtilsV2.createDBEntity();
+
+        try {
+            EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
+            List<AtlasEntityHeader> createdEntity = response.getCreatedEntities();
+            assertTrue(CollectionUtils.isNotEmpty(createdEntity));
+            String guid = createdEntity.get(0).getGuid();
+            entityStore.addClassification(Arrays.asList(guid), new AtlasClassification(aTag.getName(), "testAttribute", "test-string"));
+        } catch (AtlasBaseException e) {
+            fail("DB entity creation should've succeeded, e.getMessage() => " + e.getMessage());
+        }
+
+    }
+
+    private String randomStrWithReservedChars() {
+        return randomString() + "\"${}%";
+    }
+
+    private void validateMutationResponse(EntityMutationResponse response, EntityMutations.EntityOperation op, int expectedNumCreated) {
+        List<AtlasEntityHeader> entitiesCreated = response.getEntitiesByOperation(op);
+        Assert.assertNotNull(entitiesCreated);
+        Assert.assertEquals(entitiesCreated.size(), expectedNumCreated);
+    }
+
+    private void validateEntity(AtlasEntityExtInfo entityExtInfo, AtlasEntity actual) throws AtlasBaseException, AtlasException {
+        validateEntity(entityExtInfo, actual, entityExtInfo.getEntity(actual.getGuid()));
+    }
+
+    private void validateEntity(AtlasEntityExtInfo entityExtInfo, AtlasStruct actual, AtlasStruct expected) throws AtlasBaseException, AtlasException {
+        if (expected == null) {
+            Assert.assertNull(actual, "expected null instance. Found " + actual);
+
+            return;
+        }
+
+        Assert.assertNotNull(actual, "found null instance");
+
+        AtlasStructType entityType = (AtlasStructType) typeRegistry.getType(actual.getTypeName());
+        for (String attrName : expected.getAttributes().keySet()) {
+            Object expectedVal = expected.getAttribute(attrName);
+            Object actualVal   = actual.getAttribute(attrName);
+
+            AtlasType attrType = entityType.getAttributeType(attrName);
+            validateAttribute(entityExtInfo, actualVal, expectedVal, attrType, attrName);
+        }
+    }
+
+    private void validateAttribute(AtlasEntityExtInfo entityExtInfo, Object actual, Object expected, AtlasType attributeType, String attrName) throws AtlasBaseException, AtlasException {
+        switch(attributeType.getTypeCategory()) {
+            case OBJECT_ID_TYPE:
+                Assert.assertTrue(actual instanceof AtlasObjectId);
+                String guid = ((AtlasObjectId) actual).getGuid();
+                Assert.assertTrue(AtlasTypeUtil.isAssignedGuid(guid), "expected assigned guid. found " + guid);
+                break;
+
+            case PRIMITIVE:
+            case ENUM:
+                Assert.assertEquals(actual, expected);
+                break;
+
+            case MAP:
+                AtlasMapType mapType     = (AtlasMapType) attributeType;
+                AtlasType    valueType   = mapType.getValueType();
+                Map          actualMap   = (Map) actual;
+                Map          expectedMap = (Map) expected;
+
+                if (MapUtils.isNotEmpty(expectedMap)) {
+                    Assert.assertTrue(MapUtils.isNotEmpty(actualMap));
+
+                    // deleted entries are included in the attribute; hence use >=
+                    Assert.assertTrue(actualMap.size() >= expectedMap.size());
+
+                    for (Object key : expectedMap.keySet()) {
+                        validateAttribute(entityExtInfo, actualMap.get(key), expectedMap.get(key), valueType, attrName);
+                    }
+                }
+                break;
+
+            case ARRAY:
+                AtlasArrayType arrType      = (AtlasArrayType) attributeType;
+                AtlasType      elemType     = arrType.getElementType();
+                List           actualList   = (List) actual;
+                List           expectedList = (List) expected;
+
+                if (CollectionUtils.isNotEmpty(expectedList)) {
+                    Assert.assertTrue(CollectionUtils.isNotEmpty(actualList));
+
+                    //actual list could have deleted entities. Hence size may not match.
+                    Assert.assertTrue(actualList.size() >= expectedList.size());
+
+                    for (int i = 0; i < expectedList.size(); i++) {
+                        validateAttribute(entityExtInfo, actualList.get(i), expectedList.get(i), elemType, attrName);
+                    }
+                }
+                break;
+            case STRUCT:
+                AtlasStruct expectedStruct = (AtlasStruct) expected;
+                AtlasStruct actualStruct   = (AtlasStruct) actual;
+
+                validateEntity(entityExtInfo, actualStruct, expectedStruct);
+                break;
+            default:
+                Assert.fail("Unknown type category");
+        }
+    }
+
+    private AtlasEntity getEntityFromStore(AtlasEntityHeader header) throws AtlasBaseException {
+        return header != null ? getEntityFromStore(header.getGuid()) : null;
+    }
+
+    private AtlasEntity getEntityFromStore(String guid) throws AtlasBaseException {
+        AtlasEntityWithExtInfo entity = guid != null ? entityStore.getById(guid) : null;
+
+        return entity != null ? entity.getEntity() : null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1Test.java
new file mode 100644
index 0000000..59bedd1
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1Test.java
@@ -0,0 +1,330 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.store.graph.v1;
+
+import com.google.inject.Inject;
+import org.apache.atlas.ApplicationProperties;
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef;
+import org.apache.atlas.model.typedef.AtlasRelationshipEndDef;
+import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.apache.atlas.repository.graph.AtlasGraphProvider;
+import org.apache.atlas.type.AtlasTypeUtil;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import static org.testng.AssertJUnit.fail;
+
+/**
+ * Tests for AtlasRelationshipStoreV1
+ */
+@Guice(modules = TestModules.TestOnlyModule.class)
+public class AtlasRelationshipDefStoreV1Test {
+
+    @Inject
+    private
+    AtlasRelationshipDefStoreV1 relationshipDefStore;
+
+    @DataProvider
+    public Object[][] invalidAttributeNameWithReservedKeywords(){
+        AtlasRelationshipDef invalidAttrNameType =
+            AtlasTypeUtil.createRelationshipTypeDef("Invalid_Attribute_Type", "description","" ,
+                    AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                    AtlasRelationshipDef.PropagateTags.BOTH,
+                    new AtlasRelationshipEndDef("typeA", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                    new AtlasRelationshipEndDef("typeB", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                    AtlasTypeUtil.createRequiredAttrDef("order", "string"),
+                    AtlasTypeUtil.createRequiredAttrDef("limit", "string"));
+
+        return new Object[][] {{
+            invalidAttrNameType
+        }};
+    }
+    @DataProvider
+    public Object[][] updateValidProperties(){
+        AtlasRelationshipDef existingType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","0" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.ONE_TO_TWO,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef newType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType",
+                        "description1", // updated
+                        "1" , // updated
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH, // updated
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+
+        return new Object[][] {{
+                existingType,
+                newType
+        }};
+    }
+
+
+    @DataProvider
+    public Object[][] updateRename(){
+        AtlasRelationshipDef existingType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef newType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType2", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+
+        return new Object[][] {{
+                existingType,
+                newType
+        }};
+    }
+    @DataProvider
+    public Object[][] updateRelCat(){
+        AtlasRelationshipDef existingType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef newType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.AGGREGATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+
+        return new Object[][] {{
+                existingType,
+                newType
+        }};
+    }
+    @DataProvider
+    public Object[][] updateEnd1(){
+        AtlasRelationshipDef existingType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef changeType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeE", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef changeAttr =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr2", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef changeCardinality =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.LIST),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+
+        return new Object[][]{
+                {
+                        existingType,
+                        changeType
+                },
+                {
+                        existingType,
+                        changeAttr
+                },
+                {
+                        existingType,
+                        changeCardinality
+                }
+        };
+    }
+    @DataProvider
+    public Object[][] updateEnd2(){
+        AtlasRelationshipDef existingType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+        AtlasRelationshipDef changeType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeE", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef changeAttr =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr2", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef changeCardinality =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.LIST),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+
+        return new Object[][]{
+                {
+                        existingType,
+                        changeType
+                },
+                {
+                        existingType,
+                        changeAttr
+                },
+                {
+                        existingType,
+                        changeCardinality
+                }
+        };
+    }
+
+    @Test(dataProvider = "invalidAttributeNameWithReservedKeywords")
+    public void testCreateTypeWithReservedKeywords(AtlasRelationshipDef atlasRelationshipDef) throws AtlasException {
+        try {
+            ApplicationProperties.get().setProperty(AtlasAbstractDefStoreV1.ALLOW_RESERVED_KEYWORDS, false);
+            relationshipDefStore.create(atlasRelationshipDef, null);
+        } catch (AtlasBaseException e) {
+            Assert.assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.ATTRIBUTE_NAME_INVALID);
+        }
+    }
+
+    @Test(dataProvider = "updateValidProperties")
+    public void testupdateVertexPreUpdatepropagateTags(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef) throws AtlasBaseException {
+        AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef);
+    }
+
+    @Test(dataProvider = "updateRename")
+    public void testupdateVertexPreUpdateRename(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef)  {
+
+        try {
+            AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef);
+            fail("expected error");
+        } catch (AtlasBaseException e) {
+            if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_NAME_UPDATE)){
+                fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode());
+            }
+        }
+    }
+    @Test(dataProvider = "updateRelCat")
+    public void testupdateVertexPreUpdateRelcat(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef)  {
+
+        try {
+            AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef);
+            fail("expected error");
+        } catch (AtlasBaseException e) {
+            if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_CATEGORY_UPDATE)){
+                fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode());
+            }
+        }
+    }
+    @Test(dataProvider = "updateEnd1")
+    public void testupdateVertexPreUpdateEnd1(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef)  {
+
+        try {
+            AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef);
+            fail("expected error");
+        } catch (AtlasBaseException e) {
+            if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END1_UPDATE)){
+                fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode());
+            }
+        }
+    }
+
+    @Test(dataProvider = "updateEnd2")
+    public void testupdateVertexPreUpdateEnd2(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef)  {
+
+        try {
+            AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef);
+            fail("expected error");
+        } catch (AtlasBaseException e) {
+            if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END2_UPDATE)){
+                fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode());
+            }
+        }
+    }
+    @AfterClass
+    public void clear(){
+        AtlasGraphProvider.cleanup();
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java
new file mode 100644
index 0000000..109118e
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java
@@ -0,0 +1,112 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.store.graph.v1;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.testng.annotations.Guice;
+
+import java.util.List;
+
+import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+/**
+ * Inverse reference update test with {@link HardDeleteHandlerV1}
+ */
+@Guice(modules = TestModules.HardDeleteModule.class)
+public class AtlasRelationshipStoreHardDeleteV1Test extends AtlasRelationshipStoreV1Test {
+
+    @Override
+    protected void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception {
+        // Max should have been removed from the subordinates list, leaving only John.
+        verifyRelationshipAttributeList(jane, "subordinates", ImmutableList.of(employeeNameIdMap.get("John")));
+    }
+
+    @Override
+    protected void verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(AtlasEntity a1, AtlasEntity a2,
+                                                                            AtlasEntity a3, AtlasEntity b) {
+
+        verifyRelationshipAttributeValue(a1, "oneB", null);
+
+        verifyRelationshipAttributeValue(a2, "oneB", null);
+
+        verifyRelationshipAttributeList(b, "manyA", ImmutableList.of(getAtlasObjectId(a3)));
+    }
+
+    @Override
+    protected void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
+        verifyRelationshipAttributeValue(a1, "b", null);
+    }
+
+    @Override
+    protected void verifyRelationshipAttributeUpdate_ManyToMany_Friends(AtlasEntity max, AtlasEntity julius, AtlasEntity mike, AtlasEntity john) throws Exception {
+        AtlasObjectId johnId   = employeeNameIdMap.get("John");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
+        AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+        AtlasObjectId maxId    = employeeNameIdMap.get("Max");
+
+        List<AtlasObjectId> maxFriendsIds = toAtlasObjectIds(max.getRelationshipAttribute("friends"));
+        assertNotNull(maxFriendsIds);
+        assertEquals(maxFriendsIds.size(), 2);
+        assertObjectIdsContains(maxFriendsIds, johnId);
+        assertObjectIdsContains(maxFriendsIds, juliusId);
+
+        // Julius's updated friends: [Max]
+        List<AtlasObjectId> juliusFriendsIds = toAtlasObjectIds(julius.getRelationshipAttribute("friends"));
+        assertNotNull(juliusFriendsIds);
+        assertEquals(juliusFriendsIds.size(), 1);
+        assertObjectIdsContains(juliusFriendsIds, maxId);
+
+        // Mike's updated friends: [John]
+        List<AtlasObjectId> mikeFriendsIds = toAtlasObjectIds(mike.getRelationshipAttribute("friends"));
+        assertNotNull(mikeFriendsIds);
+        assertEquals(mikeFriendsIds.size(), 1);
+        assertObjectIdsContains(mikeFriendsIds, johnId);
+
+        // John's updated friends: [Max, Mike]
+        List<AtlasObjectId> johnFriendsIds = toAtlasObjectIds(john.getRelationshipAttribute("friends"));
+        assertNotNull(johnFriendsIds);
+        assertEquals(johnFriendsIds.size(), 2);
+        assertObjectIdsContains(johnFriendsIds, maxId);
+        assertObjectIdsContains(johnFriendsIds, mikeId);
+    }
+
+    protected void verifyRelationshipAttributeUpdate_OneToOne_Sibling(AtlasEntity julius, AtlasEntity jane, AtlasEntity mike) throws Exception {
+        AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
+
+        // Julius sibling updated to Mike
+        AtlasObjectId juliusSiblingId = toAtlasObjectId(julius.getRelationshipAttribute("sibling"));
+        assertNotNull(juliusSiblingId);
+        assertObjectIdEquals(juliusSiblingId, mikeId);
+
+        // Mike's sibling is Julius
+        AtlasObjectId mikeSiblingId = toAtlasObjectId(mike.getRelationshipAttribute("sibling"));
+        assertNotNull(mikeSiblingId);
+        assertObjectIdEquals(mikeSiblingId, juliusId);
+
+        // Julius removed from Jane's sibling (hard delete)
+        AtlasObjectId janeSiblingId = toAtlasObjectId(jane.getRelationshipAttribute("sibling"));
+        assertNull(janeSiblingId);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/042fc557/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java
new file mode 100644
index 0000000..4faf5ad
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java
@@ -0,0 +1,116 @@
+/**
+ * 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.store.graph.v1;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.testng.annotations.Guice;
+
+import java.util.List;
+
+import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+
+/**
+ * Inverse reference update test with {@link SoftDeleteHandlerV1}
+ */
+@Guice(modules = TestModules.SoftDeleteModule.class)
+public class AtlasRelationshipStoreSoftDeleteV1Test extends AtlasRelationshipStoreV1Test {
+
+    @Override
+    protected void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception {
+        // Max is still in the subordinates list, as the edge still exists with state DELETED
+        verifyRelationshipAttributeList(jane, "subordinates", ImmutableList.of(employeeNameIdMap.get("John"), employeeNameIdMap.get("Max")));
+    }
+
+    @Override
+    protected void verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(AtlasEntity a1, AtlasEntity a2,
+                                                                            AtlasEntity a3, AtlasEntity b) {
+
+        verifyRelationshipAttributeValue(a1, "oneB", b.getGuid());
+
+        verifyRelationshipAttributeValue(a2, "oneB", b.getGuid());
+
+        verifyRelationshipAttributeList(b, "manyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2), getAtlasObjectId(a3)));
+    }
+
+    @Override
+    protected void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
+        verifyRelationshipAttributeValue(a1, "b", b.getGuid());
+    }
+
+    @Override
+    protected void verifyRelationshipAttributeUpdate_ManyToMany_Friends(AtlasEntity max, AtlasEntity julius, AtlasEntity mike, AtlasEntity john) throws Exception {
+        AtlasObjectId johnId   = employeeNameIdMap.get("John");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
+        AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+        AtlasObjectId maxId    = employeeNameIdMap.get("Max");
+
+        // Max's updated friends: [Julius, John, Mike(soft deleted)]
+        List<AtlasObjectId> maxFriendsIds = toAtlasObjectIds(max.getRelationshipAttribute("friends"));
+        assertNotNull(maxFriendsIds);
+        assertEquals(maxFriendsIds.size(), 3);
+        assertObjectIdsContains(maxFriendsIds, johnId);
+        assertObjectIdsContains(maxFriendsIds, juliusId);
+        assertObjectIdsContains(maxFriendsIds, mikeId);
+
+        // Julius's updated friends: [Max]
+        List<AtlasObjectId> juliusFriendsIds = toAtlasObjectIds(julius.getRelationshipAttribute("friends"));
+        assertNotNull(juliusFriendsIds);
+        assertEquals(juliusFriendsIds.size(), 1);
+        assertObjectIdsContains(juliusFriendsIds, maxId);
+
+        // Mike's updated friends: [John, Max(soft deleted)]
+        List<AtlasObjectId> mikeFriendsIds = toAtlasObjectIds(mike.getRelationshipAttribute("friends"));
+        assertNotNull(mikeFriendsIds);
+        assertEquals(mikeFriendsIds.size(), 2);
+        assertObjectIdsContains(mikeFriendsIds, johnId);
+        assertObjectIdsContains(mikeFriendsIds, maxId);
+
+        // John's updated friends: [Max, Mike]
+        List<AtlasObjectId> johnFriendsIds = toAtlasObjectIds(john.getRelationshipAttribute("friends"));
+        assertNotNull(johnFriendsIds);
+        assertEquals(johnFriendsIds.size(), 2);
+        assertObjectIdsContains(johnFriendsIds, maxId);
+        assertObjectIdsContains(johnFriendsIds, mikeId);
+    }
+
+    protected void verifyRelationshipAttributeUpdate_OneToOne_Sibling(AtlasEntity julius, AtlasEntity jane, AtlasEntity mike) throws Exception {
+        AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
+
+        // Julius sibling updated to Mike
+        AtlasObjectId juliusSiblingId = toAtlasObjectId(julius.getRelationshipAttribute("sibling"));
+        assertNotNull(juliusSiblingId);
+        assertObjectIdEquals(juliusSiblingId, mikeId);
+
+        // Mike's sibling is Julius
+        AtlasObjectId mikeSiblingId = toAtlasObjectId(mike.getRelationshipAttribute("sibling"));
+        assertNotNull(mikeSiblingId);
+        assertObjectIdEquals(mikeSiblingId, juliusId);
+
+        // Jane's sibling is still Julius (soft delete)
+        AtlasObjectId janeSiblingId = toAtlasObjectId(jane.getRelationshipAttribute("sibling"));
+        assertNotNull(janeSiblingId);
+        assertObjectIdEquals(janeSiblingId, juliusId);
+    }
+}
\ No newline at end of file