http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/96fb0e77/webapp/src/test/java/org/apache/atlas/web/integration/EntityDiscoveryJerseyResourceIT.java ---------------------------------------------------------------------- diff --git a/webapp/src/test/java/org/apache/atlas/web/integration/EntityDiscoveryJerseyResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/integration/EntityDiscoveryJerseyResourceIT.java new file mode 100755 index 0000000..157bf97 --- /dev/null +++ b/webapp/src/test/java/org/apache/atlas/web/integration/EntityDiscoveryJerseyResourceIT.java @@ -0,0 +1,211 @@ +/** + * 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.web.integration; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.sun.jersey.core.util.MultivaluedMapImpl; +import org.apache.atlas.AtlasServiceException; +import org.apache.atlas.model.discovery.AtlasSearchResult; +import org.apache.atlas.model.discovery.AtlasSearchResult.AtlasFullTextResult; +import org.apache.atlas.model.discovery.AtlasSearchResult.AtlasQueryType; +import org.apache.atlas.model.instance.AtlasEntity.Status; +import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.typesystem.TypesDef; +import org.apache.atlas.typesystem.types.ClassType; +import org.apache.atlas.typesystem.types.DataTypes; +import org.apache.atlas.typesystem.types.EnumTypeDefinition; +import org.apache.atlas.typesystem.types.HierarchicalTypeDefinition; +import org.apache.atlas.typesystem.types.StructTypeDefinition; +import org.apache.atlas.typesystem.types.TraitType; +import org.apache.atlas.typesystem.types.utils.TypesUtil; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import javax.ws.rs.core.MultivaluedMap; +import java.util.List; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; + +/** + * Search V2 Integration Tests. + */ +public class EntityDiscoveryJerseyResourceIT extends BaseResourceIT { + private String dbName; + + @BeforeClass + public void setUp() throws Exception { + super.setUp(); + dbName = "db" + randomString(); + createTypes(); + createInstance(createHiveDBInstanceBuiltIn(dbName)); + } + + @Test + public void testSearchByDSL() throws Exception { + String dslQuery = "from "+ DATABASE_TYPE_BUILTIN + " " + QUALIFIED_NAME + "=\"" + dbName + "\""; + + AtlasSearchResult searchResult = atlasClientV2.dslSearch(dslQuery); + assertNotNull(searchResult); + assertEquals(searchResult.getQueryText(), dslQuery); + assertEquals(searchResult.getQueryType(), AtlasQueryType.DSL); + + List<AtlasEntityHeader> entities = searchResult.getEntities(); + assertNotNull(entities); + assertEquals(entities.size(), 1); + + AtlasEntityHeader dbEntity = entities.get(0); + assertEquals(dbEntity.getTypeName(), DATABASE_TYPE_BUILTIN); + assertEquals(dbEntity.getDisplayText(), dbName); + assertEquals(dbEntity.getStatus(), Status.ACTIVE); + assertNotNull(dbEntity.getGuid()); + assertNull(searchResult.getAttributes()); + assertNull(searchResult.getFullTextResult()); + } + + @Test + public void testSearchDSLLimits() throws Exception { + String dslQuery = "from "+ DATABASE_TYPE_BUILTIN + " " + QUALIFIED_NAME + "=\"" + dbName + "\""; + AtlasSearchResult searchResult = atlasClientV2.dslSearch(dslQuery); + assertNotNull(searchResult); + + //higher limit, all results returned + searchResult = atlasClientV2.dslSearchWithParams(dslQuery, 10, 0); + assertEquals(searchResult.getEntities().size(), 1); + + //default limit and offset -1, all results returned + searchResult = atlasClientV2.dslSearchWithParams(dslQuery, -1, -1); + assertEquals(searchResult.getEntities().size(), 1); + + //uses the limit parameter passed + searchResult = atlasClientV2.dslSearchWithParams(dslQuery, 1, 0); + assertEquals(searchResult.getEntities().size(), 1); + + //uses the offset parameter passed + searchResult = atlasClientV2.dslSearchWithParams(dslQuery, 10, 1); + assertNull(searchResult.getEntities()); + + //limit > 0 + searchResult = atlasClientV2.dslSearchWithParams(dslQuery, 0, 10); + assertNull(searchResult.getEntities()); + + //limit > maxlimit + searchResult = atlasClientV2.dslSearchWithParams(dslQuery, Integer.MAX_VALUE, 10); + assertNull(searchResult.getEntities()); + + //offset >= 0 + searchResult = atlasClientV2.dslSearchWithParams(dslQuery, 10, -2); + assertEquals(searchResult.getEntities().size(), 1); + } + + @Test(expectedExceptions = AtlasServiceException.class) + public void testSearchByDSLForUnknownType() throws Exception { + String dslQuery = "from blah"; + atlasClientV2.dslSearch(dslQuery); + } + + @Test + public void testSearchUsingDSL() throws Exception { + String query = "from "+ DATABASE_TYPE_BUILTIN + " " + QUALIFIED_NAME + "=\"" + dbName + "\""; + AtlasSearchResult searchResult = atlasClientV2.dslSearch(query); + assertNotNull(searchResult); + + assertEquals(searchResult.getQueryText(), query); + assertEquals(searchResult.getQueryType(), AtlasQueryType.DSL); + List<AtlasEntityHeader> entities = searchResult.getEntities(); + assertNotNull(entities); + assertEquals(entities.size(), 1); + + AtlasEntityHeader dbEntity = entities.get(0); + assertEquals(dbEntity.getTypeName(), DATABASE_TYPE_BUILTIN); + assertEquals(dbEntity.getDisplayText(), dbName); + assertEquals(dbEntity.getStatus(), Status.ACTIVE); + + assertNotNull(dbEntity.getGuid()); + assertNull(searchResult.getAttributes()); + assertNull(searchResult.getFullTextResult()); + } + + @Test + public void testSearchFullTextOnDSLFailure() throws Exception { + String query = "*"; + AtlasSearchResult searchResult = atlasClientV2.fullTextSearch(query); + assertNotNull(searchResult); + assertEquals(searchResult.getQueryText(), query); + assertEquals(searchResult.getQueryType(), AtlasQueryType.FULL_TEXT); + } + + @Test(dependsOnMethods = "testSearchDSLLimits") + public void testSearchUsingFullText() throws Exception { + AtlasSearchResult searchResult = atlasClientV2.fullTextSearchWithParams(dbName, 10, 0); + assertNotNull(searchResult); + + assertEquals(searchResult.getQueryText(), dbName); + assertEquals(searchResult.getQueryType(), AtlasQueryType.FULL_TEXT); + + List<AtlasFullTextResult> fullTextResults = searchResult.getFullTextResult(); + assertEquals(fullTextResults.size(), 1); + + AtlasFullTextResult result = fullTextResults.get(0); + assertNotNull(result.getEntity()); + assertEquals(result.getEntity().getTypeName(), DATABASE_TYPE_BUILTIN); + assertNotNull(result.getScore()); + + //API works without limit and offset + String query = dbName; + MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); + queryParams.add("query", query); + searchResult = atlasClientV2.fullTextSearch(query); + assertNotNull(searchResult); + assertEquals(searchResult.getFullTextResult().size(), 1); + + //verify passed in limits and offsets are used + //higher limit and 0 offset returns all results + searchResult = atlasClientV2.fullTextSearchWithParams(query, 10, 0); + assertEquals(searchResult.getFullTextResult().size(), 1); + + //offset is used + searchResult = atlasClientV2.fullTextSearchWithParams(query, 10, 1); + assertEquals(searchResult.getFullTextResult().size(), 1); + + //limit is used + searchResult = atlasClientV2.fullTextSearchWithParams(query, 1, 0); + assertEquals(searchResult.getFullTextResult().size(), 1); + + //higher offset returns 0 results + searchResult = atlasClientV2.fullTextSearchWithParams(query, 1, 2); + assertEquals(searchResult.getFullTextResult().size(), 1); + } + + private void createTypes() throws Exception { + HierarchicalTypeDefinition<ClassType> dslTestTypeDefinition = TypesUtil + .createClassTypeDef("dsl_test_type", ImmutableSet.<String>of(), + TypesUtil.createUniqueRequiredAttrDef("name", DataTypes.STRING_TYPE), + TypesUtil.createRequiredAttrDef("description", DataTypes.STRING_TYPE)); + + HierarchicalTypeDefinition<TraitType> classificationTraitDefinition = TypesUtil + .createTraitTypeDef("Classification", ImmutableSet.<String>of(), + TypesUtil.createRequiredAttrDef("tag", DataTypes.STRING_TYPE)); + TypesDef typesDef = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(), ImmutableList.<StructTypeDefinition>of(), + ImmutableList.of(classificationTraitDefinition), ImmutableList.of(dslTestTypeDefinition)); + createType(typesDef); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/96fb0e77/webapp/src/test/java/org/apache/atlas/web/integration/EntityJerseyResourceIT.java ---------------------------------------------------------------------- diff --git a/webapp/src/test/java/org/apache/atlas/web/integration/EntityJerseyResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/integration/EntityJerseyResourceIT.java new file mode 100755 index 0000000..310b2e3 --- /dev/null +++ b/webapp/src/test/java/org/apache/atlas/web/integration/EntityJerseyResourceIT.java @@ -0,0 +1,1101 @@ +/** + * 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.web.integration; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.core.util.MultivaluedMapImpl; +import org.apache.atlas.AtlasClient; +import org.apache.atlas.AtlasServiceException; +import org.apache.atlas.EntityAuditEvent; +import org.apache.atlas.kafka.NotificationProvider; +import org.apache.atlas.model.legacy.EntityResult; +import org.apache.atlas.notification.NotificationConsumer; +import org.apache.atlas.notification.NotificationInterface; +import org.apache.atlas.notification.entity.EntityNotification; +import org.apache.atlas.typesystem.Referenceable; +import org.apache.atlas.typesystem.Struct; +import org.apache.atlas.typesystem.TypesDef; +import org.apache.atlas.typesystem.json.InstanceSerialization; +import org.apache.atlas.typesystem.json.InstanceSerialization$; +import org.apache.atlas.typesystem.json.TypesSerialization; +import org.apache.atlas.typesystem.json.TypesSerialization$; +import org.apache.atlas.typesystem.persistence.Id; +import org.apache.atlas.typesystem.types.ClassType; +import org.apache.atlas.typesystem.types.DataTypes; +import org.apache.atlas.typesystem.types.EnumTypeDefinition; +import org.apache.atlas.typesystem.types.HierarchicalTypeDefinition; +import org.apache.atlas.typesystem.types.StructTypeDefinition; +import org.apache.atlas.typesystem.types.TraitType; +import org.apache.atlas.typesystem.types.utils.TypesUtil; +import org.apache.atlas.utils.AuthenticationUtil; +import org.apache.commons.lang.RandomStringUtils; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.fail; + + +/** + * Integration tests for Entity Jersey Resource. + */ +public class EntityJerseyResourceIT extends BaseResourceIT { + + private static final Logger LOG = LoggerFactory.getLogger(EntityJerseyResourceIT.class); + + private static final String TRAITS = "traits"; + + private NotificationInterface notificationInterface = NotificationProvider.get(); + private NotificationConsumer<EntityNotification> notificationConsumer; + + @BeforeClass + public void setUp() throws Exception { + super.setUp(); + + createTypeDefinitionsV1(); + + List<NotificationConsumer<EntityNotification>> consumers = + notificationInterface.createConsumers(NotificationInterface.NotificationType.ENTITIES, 1); + + notificationConsumer = consumers.iterator().next(); + } + + @Test + public void testCreateNestedEntities() throws Exception { + + Referenceable databaseInstance = new Referenceable(DATABASE_TYPE); + databaseInstance.set("name", "db1"); + databaseInstance.set("description", "foo database"); + + int nTables = 5; + int colsPerTable=3; + List<Referenceable> tables = new ArrayList<>(); + List<Referenceable> allColumns = new ArrayList<>(); + + for(int i = 0; i < nTables; i++) { + String tableName = "db1-table-" + i; + + Referenceable tableInstance = + new Referenceable(HIVE_TABLE_TYPE); + tableInstance.set("name", tableName); + tableInstance.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, tableName); + tableInstance.set("db", databaseInstance); + tableInstance.set("description", tableName + " table"); + tables.add(tableInstance); + + List<Referenceable> columns = new ArrayList<>(); + for(int j = 0; j < colsPerTable; j++) { + Referenceable columnInstance = new Referenceable(COLUMN_TYPE); + columnInstance.set("name", tableName + "-col-" + j); + columnInstance.set("dataType", "String"); + columnInstance.set("comment", "column " + j + " for table " + i); + allColumns.add(columnInstance); + columns.add(columnInstance); + } + tableInstance.set("columns", columns); + } + + //Create the tables. The database and columns should be created automatically, since + //the tables reference them. + List<String> entityGUIDs = atlasClientV1.createEntity(tables); + assertNotNull(entityGUIDs); + assertEquals(entityGUIDs.size(), nTables * (colsPerTable + 1) + 1); + } + + + @Test + public void testSubmitEntity() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable referenceable = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(referenceable); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + } + + @Test + public void testRequestUser() throws Exception { + Referenceable entity = new Referenceable(DATABASE_TYPE_BUILTIN); + String dbName = randomString(); + entity.set("name", dbName); + entity.set(QUALIFIED_NAME, dbName); + entity.set("clusterName", randomString()); + entity.set("description", randomString()); + entity.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, dbName); + entity.set("owner", "user1"); + entity.set("clusterName", "cl1"); + entity.set("parameters", Collections.EMPTY_MAP); + entity.set("location", "/tmp"); + + + String user = "admin"; + AtlasClient localClient = null; + if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { + localClient = new AtlasClient(atlasUrls, new String[]{"admin", "admin"}); + } else { + localClient = new AtlasClient(atlasUrls); + } + String entityId = localClient.createEntity(entity).get(0); + + List<EntityAuditEvent> events = atlasClientV1.getEntityAuditEvents(entityId, (short) 10); + assertEquals(events.size(), 1); + assertEquals(events.get(0).getUser(), user); + } + + @Test + //API should accept single entity (or jsonarray of entities) + public void testSubmitSingleEntity() throws Exception { + Referenceable databaseInstance = new Referenceable(DATABASE_TYPE_BUILTIN); + String dbName = randomString(); + databaseInstance.set("name", dbName); + databaseInstance.set(QUALIFIED_NAME, dbName); + databaseInstance.set("clusterName", randomString()); + databaseInstance.set("description", randomString()); + databaseInstance.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, dbName); + databaseInstance.set("owner", "user1"); + databaseInstance.set("clusterName", "cl1"); + databaseInstance.set("parameters", Collections.EMPTY_MAP); + databaseInstance.set("location", "/tmp"); + + JSONObject response = atlasClientV1 + .callAPIWithBody(AtlasClient.API.CREATE_ENTITY, InstanceSerialization.toJson(databaseInstance, true)); + assertNotNull(response); + Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID)); + + EntityResult entityResult = EntityResult.fromString(response.toString()); + assertEquals(entityResult.getCreatedEntities().size(), 1); + assertNotNull(entityResult.getCreatedEntities().get(0)); + } + + @Test + public void testEntityDeduping() throws Exception { + final String dbName = "db" + randomString(); + Referenceable HiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbIdReference = createInstance(HiveDBInstance); + final String dbId = dbIdReference._getId(); + + assertEntityAudit(dbId, EntityAuditEvent.EntityAuditAction.ENTITY_CREATE); + + waitForNotification(notificationConsumer, MAX_WAIT_TIME, new NotificationPredicate() { + @Override + public boolean evaluate(EntityNotification notification) throws Exception { + return notification != null && notification.getEntity().getId()._getId().equals(dbId); + } + }); + + JSONArray results = searchByDSL(String.format("%s where qualifiedName='%s'", DATABASE_TYPE_BUILTIN, dbName)); + assertEquals(results.length(), 1); + + //create entity again shouldn't create another instance with same unique attribute value + List<String> entityResults = atlasClientV1.createEntity(HiveDBInstance); + assertEquals(entityResults.size(), 0); + try { + waitForNotification(notificationConsumer, MAX_WAIT_TIME, new NotificationPredicate() { + @Override + public boolean evaluate(EntityNotification notification) throws Exception { + return notification != null && notification.getEntity().getId()._getId().equals(dbId); + } + }); + } catch (Exception e) { + //expected timeout + } + + results = searchByDSL(String.format("%s where qualifiedName='%s'", DATABASE_TYPE_BUILTIN, dbName)); + assertEquals(results.length(), 1); + + //Test the same across references + Referenceable table = new Referenceable(HIVE_TABLE_TYPE_BUILTIN); + final String tableName = randomString(); + Referenceable tableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbIdReference); + atlasClientV1.createEntity(tableInstance); + results = searchByDSL(String.format("%s where qualifiedName='%s'", DATABASE_TYPE_BUILTIN, dbName)); + assertEquals(results.length(), 1); + } + + private void assertEntityAudit(String dbid, EntityAuditEvent.EntityAuditAction auditAction) + throws Exception { + List<EntityAuditEvent> events = atlasClientV1.getEntityAuditEvents(dbid, (short) 100); + for (EntityAuditEvent event : events) { + if (event.getAction() == auditAction) { + return; + } + } + fail("Expected audit event with action = " + auditAction); + } + + @Test + public void testEntityDefinitionAcrossTypeUpdate() throws Exception { + //create type + HierarchicalTypeDefinition<ClassType> typeDefinition = TypesUtil + .createClassTypeDef(randomString(), ImmutableSet.<String>of(), + TypesUtil.createUniqueRequiredAttrDef("name", DataTypes.STRING_TYPE)); + atlasClientV1.createType(TypesSerialization.toJson(typeDefinition, false)); + + //create entity for the type + Referenceable instance = new Referenceable(typeDefinition.typeName); + instance.set("name", randomString()); + String guid = atlasClientV1.createEntity(instance).get(0); + + //update type - add attribute + typeDefinition = TypesUtil.createClassTypeDef(typeDefinition.typeName, ImmutableSet.<String>of(), + TypesUtil.createUniqueRequiredAttrDef("name", DataTypes.STRING_TYPE), + TypesUtil.createOptionalAttrDef("description", DataTypes.STRING_TYPE)); + TypesDef typeDef = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(), + ImmutableList.<StructTypeDefinition>of(), ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(), + ImmutableList.of(typeDefinition)); + atlasClientV1.updateType(typeDef); + + //Get definition after type update - new attributes should be null + Referenceable entity = atlasClientV1.getEntity(guid); + Assert.assertNull(entity.get("description")); + Assert.assertEquals(entity.get("name"), instance.get("name")); + } + + @DataProvider + public Object[][] invalidAttrValues() { + return new Object[][]{{null}, {""}}; + } + + @Test(dataProvider = "invalidAttrValues") + public void testEntityInvalidValue(String value) throws Exception { + Referenceable databaseInstance = new Referenceable(DATABASE_TYPE_BUILTIN); + databaseInstance.set("name", randomString()); + databaseInstance.set("description", value); + + try { + createInstance(databaseInstance); + Assert.fail("Expected AtlasServiceException"); + } catch (AtlasServiceException e) { + Assert.assertEquals(e.getStatus(), ClientResponse.Status.BAD_REQUEST); + } + } + + @Test + public void testGetEntityByAttribute() throws Exception { + Referenceable db1 = new Referenceable(DATABASE_TYPE_BUILTIN); + String dbName = randomString(); + db1.set(NAME, dbName); + db1.set(DESCRIPTION, randomString()); + db1.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, dbName); + db1.set("owner", "user1"); + db1.set(CLUSTER_NAME, "cl1"); + db1.set("parameters", Collections.EMPTY_MAP); + db1.set("location", "/tmp"); + createInstance(db1); + + //get entity by attribute + Referenceable referenceable = atlasClientV1.getEntity(DATABASE_TYPE_BUILTIN, QUALIFIED_NAME, dbName); + Assert.assertEquals(referenceable.getTypeName(), DATABASE_TYPE_BUILTIN); + Assert.assertEquals(referenceable.get(QUALIFIED_NAME), dbName); + } + + @Test + public void testSubmitEntityWithBadDateFormat() throws Exception { + try { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + hiveTableInstance.set("lastAccessTime", "2014-07-11"); + Id tableId = createInstance(hiveTableInstance); + Assert.fail("Was expecting an exception here "); + } catch (AtlasServiceException e) { + Assert.assertTrue( + e.getMessage().contains("\"error\":\"Cannot convert value '2014-07-11' to datatype date\"")); + } + } + + @Test + public void testAddProperty() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable referenceable = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(referenceable); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + //add property + String description = "bar table - new desc"; + addProperty(guid, "description", description); + + JSONObject response = atlasClientV1.callAPIWithBodyAndParams(AtlasClient.API.GET_ENTITY, null, guid); + Assert.assertNotNull(response); + + referenceable.set("description", description); + + //invalid property for the type + try { + addProperty(guid, "invalid_property", "bar table"); + Assert.fail("Expected AtlasServiceException"); + } catch (AtlasServiceException e) { + Assert.assertEquals(e.getStatus().getStatusCode(), Response.Status.BAD_REQUEST.getStatusCode()); + } + + String currentTime = String.valueOf(new DateTime()); + + // updating date attribute as string not supported in v2 + // addProperty(guid, "createTime", currentTime); + + response = atlasClientV1.callAPIWithBodyAndParams(AtlasClient.API.GET_ENTITY, null, guid); + Assert.assertNotNull(response); + + referenceable.set("createTime", currentTime); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testAddNullProperty() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + //add property + addProperty(guid, null, "foo bar"); + Assert.fail(); + } + + @Test(enabled = false) + public void testAddNullPropertyValue() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + //add property + try { + addProperty(guid, "description", null); + Assert.fail("Expected AtlasServiceException"); + } catch(AtlasServiceException e) { + Assert.assertEquals(e.getStatus().getStatusCode(), Response.Status.BAD_REQUEST.getStatusCode()); + } + } + + @Test + public void testAddReferenceProperty() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + //Create new db instance + dbName = "db" + randomString(); + Referenceable databaseInstance = new Referenceable(DATABASE_TYPE_BUILTIN); + databaseInstance.set(NAME, dbName); + databaseInstance.set(QUALIFIED_NAME, dbName); + databaseInstance.set(CLUSTER_NAME, randomString()); + databaseInstance.set("description", "new database"); + databaseInstance.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, dbName); + databaseInstance.set("owner", "user1"); + databaseInstance.set(CLUSTER_NAME, "cl1"); + databaseInstance.set("parameters", Collections.EMPTY_MAP); + databaseInstance.set("location", "/tmp"); + + Id dbInstance = createInstance(databaseInstance); + String newDBId = dbInstance._getId(); + + //Add reference property + addProperty(guid, "db", newDBId); + } + + @Test + public void testGetEntityDefinition() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + Referenceable entity = atlasClientV1.getEntity(guid); + Assert.assertNotNull(entity); + } + + private void addProperty(String guid, String property, String value) throws AtlasServiceException { + EntityResult entityResult = atlasClientV1.updateEntityAttribute(guid, property, value); + assertEquals(entityResult.getUpdateEntities().size(), 1); + assertEquals(entityResult.getUpdateEntities().get(0), guid); + } + + @Test(expectedExceptions = AtlasServiceException.class) + public void testGetInvalidEntityDefinition() throws Exception { + + JSONObject response = atlasClientV1.callAPIWithBodyAndParams(AtlasClient.API.GET_ENTITY, null, "blah"); + + Assert.assertNotNull(response); + + Assert.assertNotNull(response.get(AtlasClient.ERROR)); + } + + @Test + public void testGetEntityList() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + List<String> entities = atlasClientV1.listEntities(HIVE_TABLE_TYPE_BUILTIN); + Assert.assertNotNull(entities); + Assert.assertTrue(entities.contains(guid)); + } + + @Test(expectedExceptions = AtlasServiceException.class) + public void testGetEntityListForBadEntityType() throws Exception { + MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); + queryParams.add("type", "blah"); + + JSONObject response = atlasClientV1.callAPIWithQueryParams(AtlasClient.API.GET_ENTITY, queryParams); + assertNotNull(response); + Assert.assertNotNull(response.get(AtlasClient.ERROR)); + } + + + @Test + public void testGetEntityListForNoInstances() throws Exception { + String typeName = addNewType(); + + MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); + queryParams.add("type", typeName); + + JSONObject response = atlasClientV1.callAPIWithQueryParams(AtlasClient.API.GET_ENTITY, queryParams); + assertNotNull(response); + Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID)); + + final JSONArray list = response.getJSONArray(AtlasClient.RESULTS); + Assert.assertEquals(list.length(), 0); + } + + private String addNewType() throws Exception { + String typeName = "test" + randomString(); + HierarchicalTypeDefinition<ClassType> testTypeDefinition = TypesUtil + .createClassTypeDef(typeName, ImmutableSet.<String>of(), + TypesUtil.createRequiredAttrDef("name", DataTypes.STRING_TYPE), + TypesUtil.createRequiredAttrDef("description", DataTypes.STRING_TYPE)); + + String typesAsJSON = TypesSerialization.toJson(testTypeDefinition, false); + createType(typesAsJSON); + return typeName; + } + + @Test + public void testGetTraitNames() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + List<String> traits = atlasClientV1.listTraits(guid); + assertNotNull(traits); + Assert.assertEquals(traits.size(), 7); + } + + @Test + public void testAddTrait() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + String traitName = "PII_Trait" + randomString(); + HierarchicalTypeDefinition<TraitType> piiTrait = + TypesUtil.createTraitTypeDef(traitName, ImmutableSet.<String>of()); + String traitDefinitionAsJSON = TypesSerialization$.MODULE$.toJson(piiTrait, true); + LOG.debug("traitDefinitionAsJSON = {}", traitDefinitionAsJSON); + createType(traitDefinitionAsJSON); + + Struct traitInstance = new Struct(traitName); + + atlasClientV1.addTrait(guid, traitInstance); + assertEntityAudit(guid, EntityAuditEvent.EntityAuditAction.TAG_ADD); + } + + @Test + public void testGetTraitDefinitionForEntity() throws Exception{ + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + String traitName = "PII_Trait" + randomString(); + HierarchicalTypeDefinition<TraitType> piiTrait = + TypesUtil.createTraitTypeDef(traitName, ImmutableSet.<String>of()); + String traitDefinitionAsJSON = TypesSerialization$.MODULE$.toJson(piiTrait, true); + LOG.debug("traitDefinitionAsJSON = {}", traitDefinitionAsJSON); + createType(traitDefinitionAsJSON); + + Struct traitInstance = new Struct(traitName); + atlasClientV1.addTrait(guid, traitInstance); + Struct traitDef = atlasClientV1.getTraitDefinition(guid, traitName); + Assert.assertEquals(traitDef.getTypeName(), traitName); + + + List<Struct> allTraitDefs = atlasClientV1.listTraitDefinitions(guid); + System.out.println(allTraitDefs.toString()); + Assert.assertEquals(allTraitDefs.size(), 8); + } + + @Test + public void testAddExistingTrait() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + String traitName = "PII_Trait" + randomString(); + HierarchicalTypeDefinition<TraitType> piiTrait = + TypesUtil.createTraitTypeDef(traitName, ImmutableSet.<String>of()); + String traitDefinitionAsJSON = TypesSerialization$.MODULE$.toJson(piiTrait, true); + LOG.debug("traitDefinitionAsJSON = {}", traitDefinitionAsJSON); + createType(traitDefinitionAsJSON); + + Struct traitInstance = new Struct(traitName); + atlasClientV1.addTrait(guid, traitInstance); + + try { + atlasClientV1.addTrait(guid, traitInstance); + fail("Duplicate trait addition should've failed"); + } catch (AtlasServiceException e) { + assertEquals(e.getStatus(), ClientResponse.Status.BAD_REQUEST); + } + } + + @Test + public void testAddTraitWithAttribute() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + final String traitName = "PII_Trait" + randomString(); + HierarchicalTypeDefinition<TraitType> piiTrait = TypesUtil + .createTraitTypeDef(traitName, ImmutableSet.<String>of(), + TypesUtil.createRequiredAttrDef("type", DataTypes.STRING_TYPE)); + String traitDefinitionAsJSON = TypesSerialization$.MODULE$.toJson(piiTrait, true); + LOG.debug("traitDefinitionAsJSON = {}", traitDefinitionAsJSON); + createType(traitDefinitionAsJSON); + + Struct traitInstance = new Struct(traitName); + traitInstance.set("type", "SSN"); + atlasClientV1.addTrait(guid, traitInstance); + + // verify the response + Referenceable entity = atlasClientV1.getEntity(guid); + Assert.assertNotNull(entity); + Assert.assertEquals(entity.getId()._getId(), guid); + + assertNotNull(entity.getTrait(traitName)); + assertEquals(entity.getTrait(traitName).get("type"), traitInstance.get("type")); + } + + @Test(expectedExceptions = AtlasServiceException.class) + public void testAddTraitWithNoRegistration() throws Exception { + final String traitName = "PII_Trait" + randomString(); + HierarchicalTypeDefinition<TraitType> piiTrait = + TypesUtil.createTraitTypeDef(traitName, ImmutableSet.<String>of()); + String traitDefinitionAsJSON = TypesSerialization$.MODULE$.toJson(piiTrait, true); + LOG.debug("traitDefinitionAsJSON = {}", traitDefinitionAsJSON); + + Struct traitInstance = new Struct(traitName); + String traitInstanceAsJSON = InstanceSerialization$.MODULE$.toJson(traitInstance, true); + LOG.debug("traitInstanceAsJSON = {}", traitInstanceAsJSON); + + atlasClientV1.callAPIWithBodyAndParams(AtlasClient.API.CREATE_ENTITY, traitInstanceAsJSON, "random", TRAITS); + } + + @Test + public void testDeleteTrait() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + String traitName = "PII_Trait" + randomString(); + HierarchicalTypeDefinition<TraitType> piiTrait = + TypesUtil.createTraitTypeDef(traitName, ImmutableSet.<String>of()); + String traitDefinitionAsJSON = TypesSerialization$.MODULE$.toJson(piiTrait, true); + LOG.debug("traitDefinitionAsJSON = {}", traitDefinitionAsJSON); + createType(traitDefinitionAsJSON); + + Struct traitInstance = new Struct(traitName); + + atlasClientV1.addTrait(guid, traitInstance); + assertEntityAudit(guid, EntityAuditEvent.EntityAuditAction.TAG_ADD); + + atlasClientV1.deleteTrait(guid, traitName); + + try { + atlasClientV1.getTraitDefinition(guid, traitName); + fail("Deleted trait definition shouldn't exist"); + } catch (AtlasServiceException e) { + assertEquals(e.getStatus(), ClientResponse.Status.NOT_FOUND); + assertEntityAudit(guid, EntityAuditEvent.EntityAuditAction.TAG_DELETE); + } + } + + @Test(expectedExceptions = AtlasServiceException.class) + public void testDeleteTraitNonExistent() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + final String traitName = "blah_trait"; + atlasClientV1.deleteTrait(guid, traitName); + fail("trait=" + traitName + " should be defined in type system before it can be deleted"); + } + + @Test + public void testDeleteExistentTraitNonExistentForEntity() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id id = createInstance(hiveTableInstance); + + final String guid = id._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + final String traitName = "PII_Trait" + randomString(); + HierarchicalTypeDefinition<TraitType> piiTrait = TypesUtil + .createTraitTypeDef(traitName, ImmutableSet.<String>of(), + TypesUtil.createRequiredAttrDef("type", DataTypes.STRING_TYPE)); + String traitDefinitionAsJSON = TypesSerialization$.MODULE$.toJson(piiTrait, true); + createType(traitDefinitionAsJSON); + + try { + atlasClientV1.deleteTrait(guid, traitName); + fail("Call should've failed for deletion of invalid trait"); + } catch (AtlasServiceException e) { + assertNotNull(e); + assertNotNull(e.getStatus()); + assertEquals(e.getStatus(), ClientResponse.Status.NOT_FOUND); + } + } + + private String random() { + return RandomStringUtils.random(10); + } + + @Test + public void testUTF8() throws Exception { + //Type names cannot be arbitrary UTF8 characters. See org.apache.atlas.type.AtlasTypeUtil#validateType() + String classType = randomString(); + String attrName = random(); + String attrValue = random(); + + HierarchicalTypeDefinition<ClassType> classTypeDefinition = TypesUtil + .createClassTypeDef(classType, ImmutableSet.<String>of(), + TypesUtil.createUniqueRequiredAttrDef(attrName, DataTypes.STRING_TYPE)); + TypesDef typesDef = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(), ImmutableList.<StructTypeDefinition>of(), + ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(), + ImmutableList.of(classTypeDefinition)); + createType(typesDef); + + Referenceable instance = new Referenceable(classType); + instance.set(attrName, attrValue); + Id guid = createInstance(instance); + + JSONObject response = atlasClientV1.callAPIWithBodyAndParams(AtlasClient.API.GET_ENTITY, null, guid._getId()); + Referenceable getReferenceable = InstanceSerialization.fromJsonReferenceable(response.getString(AtlasClient.DEFINITION), true); + Assert.assertEquals(getReferenceable.get(attrName), attrValue); + } + + + @Test + public void testPartialUpdate() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id tableId = createInstance(hiveTableInstance); + + final String guid = tableId._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + String colName = "col1"+randomString(); + final List<Referenceable> columns = new ArrayList<>(); + Map<String, Object> values = new HashMap<>(); + values.put(NAME, colName); + values.put("comment", "col1 comment"); + values.put(QUALIFIED_NAME, "default.table.col1@"+colName); + values.put("comment", "col1 comment"); + values.put("type", "string"); + values.put("owner", "user1"); + values.put("position", 0); + values.put("description", "col1"); + values.put("table", tableId); //table is a required reference, can't be null + + Referenceable ref = new Referenceable(BaseResourceIT.COLUMN_TYPE_BUILTIN, values); + columns.add(ref); + Referenceable tableUpdated = new Referenceable(BaseResourceIT.HIVE_TABLE_TYPE_BUILTIN, new HashMap<String, Object>() {{ + put("columns", columns); + }}); + + LOG.debug("Updating entity= {}", tableUpdated); + EntityResult entityResult = atlasClientV1.updateEntity(guid, tableUpdated); + assertEquals(entityResult.getUpdateEntities().size(), 1); + assertEquals(entityResult.getUpdateEntities().get(0), guid); + + Referenceable entity = atlasClientV1.getEntity(guid); + List<Referenceable> refs = (List<Referenceable>) entity.get("columns"); + + Assert.assertTrue(refs.get(0).equalsContents(columns.get(0))); + + //Update by unique attribute + values.put("type", "int"); + ref = new Referenceable(BaseResourceIT.COLUMN_TYPE_BUILTIN, values); + columns.set(0, ref); + tableUpdated = new Referenceable(BaseResourceIT.HIVE_TABLE_TYPE_BUILTIN, new HashMap<String, Object>() {{ + put("columns", columns); + }}); + + LOG.debug("Updating entity= {}", tableUpdated); + entityResult = atlasClientV1.updateEntity(BaseResourceIT.HIVE_TABLE_TYPE_BUILTIN, AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, + (String) hiveTableInstance.get(QUALIFIED_NAME), tableUpdated); + assertEquals(entityResult.getUpdateEntities().size(), 2); + assertEquals(entityResult.getUpdateEntities().get(1), guid); + + entity = atlasClientV1.getEntity(guid); + refs = (List<Referenceable>) entity.get("columns"); + + Assert.assertTrue(refs.get(0).getValuesMap().equals(values)); + Assert.assertEquals(refs.get(0).get("type"), "int"); + } + + @Test + public void testCompleteUpdate() throws Exception { + String dbName = "db" + randomString(); + String tableName = "table" + randomString(); + Referenceable hiveDBInstance = createHiveDBInstanceBuiltIn(dbName); + Id dbId = createInstance(hiveDBInstance); + Referenceable hiveTableInstance = createHiveTableInstanceBuiltIn(dbName, tableName, dbId); + Id tableId = createInstance(hiveTableInstance); + + final String guid = tableId._getId(); + try { + Assert.assertNotNull(UUID.fromString(guid)); + } catch (IllegalArgumentException e) { + Assert.fail("Response is not a guid, " + guid); + } + + final List<Referenceable> columns = new ArrayList<>(); + Map<String, Object> values1 = new HashMap<>(); + values1.put(NAME, "col3"); + values1.put(QUALIFIED_NAME, "default.table.col3@cl1"); + values1.put("comment", "col3 comment"); + values1.put("type", "string"); + values1.put("owner", "user1"); + values1.put("position", 0); + values1.put("description", "col3"); + values1.put("table", tableId); + + + Map<String, Object> values2 = new HashMap<>(); + values2.put(NAME, "col4"); + values2.put(QUALIFIED_NAME, "default.table.col4@cl1"); + values2.put("comment", "col4 comment"); + values2.put("type", "string"); + values2.put("owner", "user2"); + values2.put("position", 1); + values2.put("description", "col4"); + values2.put("table", tableId); + + Referenceable ref1 = new Referenceable(BaseResourceIT.COLUMN_TYPE_BUILTIN, values1); + Referenceable ref2 = new Referenceable(BaseResourceIT.COLUMN_TYPE_BUILTIN, values2); + columns.add(ref1); + columns.add(ref2); + hiveTableInstance.set("columns", columns); + LOG.debug("Replacing entity= {}", hiveTableInstance); + + EntityResult updateEntity = atlasClientV1.updateEntities(hiveTableInstance); + + assertNotNull(updateEntity.getUpdateEntities()); + + hiveTableInstance = atlasClientV1.getEntity(guid); + List<Referenceable> refs = (List<Referenceable>) hiveTableInstance.get("columns"); + Assert.assertEquals(refs.size(), 2); + + Assert.assertTrue(refs.get(0).getValuesMap().equals(values1)); + Assert.assertTrue(refs.get(1).getValuesMap().equals(values2)); + } + + @Test + public void testDeleteEntitiesViaRestApi() throws Exception { + // Create 2 database entities + Referenceable db1 = new Referenceable(DATABASE_TYPE_BUILTIN); + String dbName = randomString(); + db1.set(NAME, dbName); + db1.set(DESCRIPTION, randomString()); + db1.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, dbName); + db1.set("owner", "user1"); + db1.set(CLUSTER_NAME, "cl1"); + db1.set("parameters", Collections.EMPTY_MAP); + db1.set("location", "/tmp"); + Id db1Id = createInstance(db1); + + Referenceable db2 = new Referenceable(DATABASE_TYPE_BUILTIN); + String dbName2 = randomString(); + db2.set(NAME, dbName2); + db2.set(QUALIFIED_NAME, dbName2); + db2.set(CLUSTER_NAME, randomString()); + db2.set(DESCRIPTION, randomString()); + db2.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, dbName2); + db2.set("owner", "user2"); + db2.set(CLUSTER_NAME, "cl1"); + db2.set("parameters", Collections.EMPTY_MAP); + db2.set("location", "/tmp"); + Id db2Id = createInstance(db2); + + // Delete the database entities + MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); + queryParams.add(AtlasClient.GUID.toLowerCase(), db1Id._getId()); + queryParams.add(AtlasClient.GUID.toLowerCase(), db2Id._getId()); + + JSONObject response = atlasClientV1.callAPIWithQueryParams(AtlasClient.API.DELETE_ENTITIES, queryParams); + List<String> deletedGuidsList = EntityResult.fromString(response.toString()).getDeletedEntities(); + Assert.assertTrue(deletedGuidsList.contains(db1Id._getId())); + Assert.assertTrue(deletedGuidsList.contains(db2Id._getId())); + + // Verify entities were deleted from the repository. + for (String guid : deletedGuidsList) { + Referenceable entity = atlasClientV1.getEntity(guid); + assertEquals(entity.getId().getState(), Id.EntityState.DELETED); + } + } + + @Test + public void testDeleteEntitiesViaClientApi() throws Exception { + // Create 2 database entities + Referenceable db1 = new Referenceable(DATABASE_TYPE_BUILTIN); + String dbName = randomString(); + db1.set("name", dbName); + db1.set("description", randomString()); + db1.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, dbName); + db1.set("owner", "user1"); + db1.set(CLUSTER_NAME, "cl1"); + db1.set("parameters", Collections.EMPTY_MAP); + db1.set("location", "/tmp"); + Id db1Id = createInstance(db1); + Referenceable db2 = new Referenceable(DATABASE_TYPE_BUILTIN); + String dbName2 = randomString(); + db2.set("name", dbName2); + db2.set(QUALIFIED_NAME, dbName2); + db2.set(CLUSTER_NAME, randomString()); + db2.set("description", randomString()); + db2.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, dbName2); + db2.set("owner", "user2"); + db2.set("clusterName", "cl1"); + db2.set("parameters", Collections.EMPTY_MAP); + db2.set("location", "/tmp"); + Id db2Id = createInstance(db2); + + // Delete the database entities + List<String> deletedGuidsList = + atlasClientV1.deleteEntities(db1Id._getId(), db2Id._getId()).getDeletedEntities(); + // Verify that deleteEntities() response has database entity guids + Assert.assertEquals(deletedGuidsList.size(), 2); + Assert.assertTrue(deletedGuidsList.contains(db1Id._getId())); + Assert.assertTrue(deletedGuidsList.contains(db2Id._getId())); + + // Verify entities were deleted from the repository. + for (String guid : deletedGuidsList) { + Referenceable entity = atlasClientV1.getEntity(guid); + assertEquals(entity.getId().getState(), Id.EntityState.DELETED); + } + } + + @Test + public void testDeleteEntityByUniqAttribute() throws Exception { + // Create database entity + Referenceable db1 = new Referenceable(DATABASE_TYPE_BUILTIN); + String dbName = randomString(); + db1.set(NAME, dbName); + db1.set(QUALIFIED_NAME, dbName); + db1.set(CLUSTER_NAME, randomString()); + db1.set(DESCRIPTION, randomString()); + db1.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, dbName); + db1.set("owner", "user1"); + db1.set(CLUSTER_NAME, "cl1"); + db1.set("parameters", Collections.EMPTY_MAP); + db1.set("location", "/tmp"); + Id db1Id = createInstance(db1); + + // Delete the database entity + List<String> deletedGuidsList = atlasClientV1.deleteEntity(DATABASE_TYPE_BUILTIN, QUALIFIED_NAME, dbName).getDeletedEntities(); + + // Verify that deleteEntities() response has database entity guids + Assert.assertEquals(deletedGuidsList.size(), 1); + Assert.assertTrue(deletedGuidsList.contains(db1Id._getId())); + + // Verify entities were deleted from the repository. + for (String guid : deletedGuidsList) { + Referenceable entity = atlasClientV1.getEntity(guid); + assertEquals(entity.getId().getState(), Id.EntityState.DELETED); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/96fb0e77/webapp/src/test/java/org/apache/atlas/web/integration/EntityLineageJerseyResourceIT.java ---------------------------------------------------------------------- diff --git a/webapp/src/test/java/org/apache/atlas/web/integration/EntityLineageJerseyResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/integration/EntityLineageJerseyResourceIT.java new file mode 100644 index 0000000..55c56c2 --- /dev/null +++ b/webapp/src/test/java/org/apache/atlas/web/integration/EntityLineageJerseyResourceIT.java @@ -0,0 +1,190 @@ +/** + * 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.web.integration; + +import com.google.common.collect.ImmutableList; +import com.google.gson.Gson; +import com.sun.jersey.core.util.MultivaluedMapImpl; +import org.apache.atlas.AtlasClient; +import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.model.lineage.AtlasLineageInfo; +import org.apache.atlas.typesystem.Referenceable; +import org.apache.atlas.typesystem.persistence.Id; +import org.codehaus.jettison.json.JSONObject; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.apache.atlas.AtlasBaseClient.APIInfo; + +/** + * Entity Lineage v2 Integration Tests. + */ +public class EntityLineageJerseyResourceIT extends DataSetLineageJerseyResourceIT { + private static final String BASE_URI = "api/atlas/v2/lineage"; + private static final APIInfo LINEAGE_V2_API = new APIInfo(BASE_URI, "GET", Response.Status.OK); + private static final String INPUT_DIRECTION = "INPUT"; + private static final String OUTPUT_DIRECTION = "OUTPUT"; + private static final String BOTH_DIRECTION = "BOTH"; + private static final String DIRECTION_PARAM = "direction"; + private static final String DEPTH_PARAM = "depth"; + + private String salesFactTable; + private String salesMonthlyTable; + private String salesDBName; + Gson gson = new Gson(); + + @BeforeClass + public void setUp() throws Exception { + super.setUp(); + + createTypeDefinitionsV1(); + setupInstances(); + } + + @Test + public void testInputLineageInfo() throws Exception { + String tableId = atlasClientV1.getEntity(HIVE_TABLE_TYPE, + AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, salesMonthlyTable).getId()._getId(); + + MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); + queryParams.add(DIRECTION_PARAM, INPUT_DIRECTION); + queryParams.add(DEPTH_PARAM, "5"); + JSONObject response = atlasClientV1.callAPI(LINEAGE_V2_API, JSONObject.class, queryParams, tableId); + Assert.assertNotNull(response); + System.out.println("input lineage info = " + response + ); + + AtlasLineageInfo inputLineageInfo = gson.fromJson(response.toString(), AtlasLineageInfo.class); + + Map<String, AtlasEntityHeader> entities = inputLineageInfo.getGuidEntityMap(); + Assert.assertNotNull(entities); + + Set<AtlasLineageInfo.LineageRelation> relations = inputLineageInfo.getRelations(); + Assert.assertNotNull(relations); + + Assert.assertEquals(entities.size(), 6); + Assert.assertEquals(relations.size(), 5); + Assert.assertEquals(inputLineageInfo.getLineageDirection(), AtlasLineageInfo.LineageDirection.INPUT); + Assert.assertEquals(inputLineageInfo.getLineageDepth(), 5); + Assert.assertEquals(inputLineageInfo.getBaseEntityGuid(), tableId); + } + + @Test + public void testOutputLineageInfo() throws Exception { + String tableId = atlasClientV1.getEntity(HIVE_TABLE_TYPE, + AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, salesFactTable).getId()._getId(); + + MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); + queryParams.add(DIRECTION_PARAM, OUTPUT_DIRECTION); + queryParams.add(DEPTH_PARAM, "5"); + JSONObject response = atlasClientV1.callAPI(LINEAGE_V2_API, JSONObject.class, queryParams, tableId); + + Assert.assertNotNull(response); + System.out.println("output lineage info = " + response); + + AtlasLineageInfo outputLineageInfo = gson.fromJson(response.toString(), AtlasLineageInfo.class); + + Map<String, AtlasEntityHeader> entities = outputLineageInfo.getGuidEntityMap(); + Assert.assertNotNull(entities); + + Set<AtlasLineageInfo.LineageRelation> relations = outputLineageInfo.getRelations(); + Assert.assertNotNull(relations); + + Assert.assertEquals(entities.size(), 5); + Assert.assertEquals(relations.size(), 4); + Assert.assertEquals(outputLineageInfo.getLineageDirection(), AtlasLineageInfo.LineageDirection.OUTPUT); + Assert.assertEquals(outputLineageInfo.getLineageDepth(), 5); + Assert.assertEquals(outputLineageInfo.getBaseEntityGuid(), tableId); + } + + @Test + public void testLineageInfo() throws Exception { + String tableId = atlasClientV1.getEntity(HIVE_TABLE_TYPE, + AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, salesMonthlyTable).getId()._getId(); + + MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); + queryParams.add(DIRECTION_PARAM, BOTH_DIRECTION); + queryParams.add(DEPTH_PARAM, "5"); + JSONObject response = atlasClientV1.callAPI(LINEAGE_V2_API, JSONObject.class, queryParams, tableId); + + Assert.assertNotNull(response); + System.out.println("both lineage info = " + response); + + AtlasLineageInfo bothLineageInfo = gson.fromJson(response.toString(), AtlasLineageInfo.class); + + Map<String, AtlasEntityHeader> entities = bothLineageInfo.getGuidEntityMap(); + Assert.assertNotNull(entities); + + Set<AtlasLineageInfo.LineageRelation> relations = bothLineageInfo.getRelations(); + Assert.assertNotNull(relations); + + Assert.assertEquals(entities.size(), 6); + Assert.assertEquals(relations.size(), 5); + Assert.assertEquals(bothLineageInfo.getLineageDirection(), AtlasLineageInfo.LineageDirection.BOTH); + Assert.assertEquals(bothLineageInfo.getLineageDepth(), 5); + Assert.assertEquals(bothLineageInfo.getBaseEntityGuid(), tableId); + } + + private void setupInstances() throws Exception { + salesDBName = "Sales" + randomString(); + Id salesDB = database(salesDBName, "Sales Database", "John ETL", "hdfs://host:8000/apps/warehouse/sales"); + + List<Referenceable> salesFactColumns = ImmutableList + .of(column("time_id", "int", "time id"), column("product_id", "int", "product id"), + column("customer_id", "int", "customer id"), + column("sales", "double", "product id")); + + salesFactTable = "sales_fact" + randomString(); + Id salesFact = table(salesFactTable, "sales fact table", salesDB, "Joe", "MANAGED", salesFactColumns); + + List<Referenceable> timeDimColumns = ImmutableList + .of(column("time_id", "int", "time id"), column("dayOfYear", "int", "day Of Year"), + column("weekDay", "int", "week Day")); + + Id timeDim = + table("time_dim" + randomString(), "time dimension table", salesDB, "John Doe", "EXTERNAL", + timeDimColumns); + + Id reportingDB = + database("Reporting" + randomString(), "reporting database", "Jane BI", + "hdfs://host:8000/apps/warehouse/reporting"); + + Id salesFactDaily = + table("sales_fact_daily_mv" + randomString(), "sales fact daily materialized view", reportingDB, + "Joe BI", "MANAGED", salesFactColumns); + + loadProcess("loadSalesDaily" + randomString(), "John ETL", ImmutableList.of(salesFact, timeDim), + ImmutableList.of(salesFactDaily), "create table as select ", "plan", "id", "graph"); + + salesMonthlyTable = "sales_fact_monthly_mv" + randomString(); + Id salesFactMonthly = + table(salesMonthlyTable, "sales fact monthly materialized view", reportingDB, "Jane BI", + "MANAGED", salesFactColumns); + + loadProcess("loadSalesMonthly" + randomString(), "John ETL", ImmutableList.of(salesFactDaily), + ImmutableList.of(salesFactMonthly), "create table as select ", "plan", "id", "graph"); + } +}
