Repository: incubator-atlas Updated Branches: refs/heads/master 35d42ad19 -> c0b4975bc
ATLAS-300 Need additional integration test coverage for entity notifications (tbeerbower via shwethags) Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/c0b4975b Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/c0b4975b Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/c0b4975b Branch: refs/heads/master Commit: c0b4975bcbaeb195703241bc37796624aed8d04d Parents: 35d42ad Author: Shwetha GS <[email protected]> Authored: Tue Nov 17 15:36:21 2015 +0530 Committer: Shwetha GS <[email protected]> Committed: Tue Nov 17 15:40:57 2015 +0530 ---------------------------------------------------------------------- .../entity/EntityNotificationImplTest.java | 146 ++++----- release-log.txt | 1 + .../notification/EntityNotificationIT.java | 305 ++++++++++++++++--- 3 files changed, 331 insertions(+), 121 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c0b4975b/notification/src/test/java/org/apache/atlas/notification/entity/EntityNotificationImplTest.java ---------------------------------------------------------------------- diff --git a/notification/src/test/java/org/apache/atlas/notification/entity/EntityNotificationImplTest.java b/notification/src/test/java/org/apache/atlas/notification/entity/EntityNotificationImplTest.java index aff9d04..6a0a920 100644 --- a/notification/src/test/java/org/apache/atlas/notification/entity/EntityNotificationImplTest.java +++ b/notification/src/test/java/org/apache/atlas/notification/entity/EntityNotificationImplTest.java @@ -42,108 +42,108 @@ import static org.testng.Assert.assertTrue; */ public class EntityNotificationImplTest { - @Test - public void testGetEntity() throws Exception { - Referenceable entity = getEntity("id"); + @Test + public void testGetEntity() throws Exception { + Referenceable entity = getEntity("id"); - EntityNotificationImpl entityNotification = - new EntityNotificationImpl(entity, EntityNotification.OperationType.ENTITY_CREATE, - Collections.<IStruct>emptyList()); + EntityNotificationImpl entityNotification = + new EntityNotificationImpl(entity, EntityNotification.OperationType.ENTITY_CREATE, + Collections.<IStruct>emptyList()); - assertEquals(entity, entityNotification.getEntity()); - } + assertEquals(entity, entityNotification.getEntity()); + } - @Test - public void testGetOperationType() throws Exception { - Referenceable entity = getEntity("id"); + @Test + public void testGetOperationType() throws Exception { + Referenceable entity = getEntity("id"); - EntityNotificationImpl entityNotification = - new EntityNotificationImpl(entity, EntityNotification.OperationType.ENTITY_CREATE, - Collections.<IStruct>emptyList()); + EntityNotificationImpl entityNotification = + new EntityNotificationImpl(entity, EntityNotification.OperationType.ENTITY_CREATE, + Collections.<IStruct>emptyList()); - assertEquals(EntityNotification.OperationType.ENTITY_CREATE, entityNotification.getOperationType()); - } + assertEquals(EntityNotification.OperationType.ENTITY_CREATE, entityNotification.getOperationType()); + } - @Test - public void testGetAllTraits() throws Exception { - Referenceable entity = getEntity("id"); - String traitName = "MyTrait"; - List<IStruct> traitInfo = new LinkedList<>(); - IStruct trait = new Struct(traitName, Collections.<String, Object>emptyMap()); - traitInfo.add(trait); + @Test + public void testGetAllTraits() throws Exception { + Referenceable entity = getEntity("id"); + String traitName = "MyTrait"; + List<IStruct> traitInfo = new LinkedList<>(); + IStruct trait = new Struct(traitName, Collections.<String, Object>emptyMap()); + traitInfo.add(trait); - EntityNotificationImpl entityNotification = - new EntityNotificationImpl(entity, EntityNotification.OperationType.TRAIT_ADD, traitInfo); + EntityNotificationImpl entityNotification = + new EntityNotificationImpl(entity, EntityNotification.OperationType.TRAIT_ADD, traitInfo); - assertEquals(traitInfo, entityNotification.getAllTraits()); - } + assertEquals(traitInfo, entityNotification.getAllTraits()); + } - @Test - public void testGetAllTraits_superTraits() throws Exception { + @Test + public void testGetAllTraits_superTraits() throws Exception { - TypeSystem typeSystem = mock(TypeSystem.class); + TypeSystem typeSystem = mock(TypeSystem.class); - String traitName = "MyTrait"; - IStruct myTrait = new Struct(traitName); + String traitName = "MyTrait"; + IStruct myTrait = new Struct(traitName); - String superTraitName = "MySuperTrait"; + String superTraitName = "MySuperTrait"; - TraitType traitDef = mock(TraitType.class); - Set<String> superTypeNames = Collections.singleton(superTraitName); + TraitType traitDef = mock(TraitType.class); + Set<String> superTypeNames = Collections.singleton(superTraitName); - TraitType superTraitDef = mock(TraitType.class); - Set<String> superSuperTypeNames = Collections.emptySet(); + TraitType superTraitDef = mock(TraitType.class); + Set<String> superSuperTypeNames = Collections.emptySet(); - Referenceable entity = getEntity("id", myTrait); + Referenceable entity = getEntity("id", myTrait); - when(typeSystem.getDataType(TraitType.class, traitName)).thenReturn(traitDef); - when(typeSystem.getDataType(TraitType.class, superTraitName)).thenReturn(superTraitDef); + when(typeSystem.getDataType(TraitType.class, traitName)).thenReturn(traitDef); + when(typeSystem.getDataType(TraitType.class, superTraitName)).thenReturn(superTraitDef); - when(traitDef.getAllSuperTypeNames()).thenReturn(superTypeNames); - when(superTraitDef.getAllSuperTypeNames()).thenReturn(superSuperTypeNames); + when(traitDef.getAllSuperTypeNames()).thenReturn(superTypeNames); + when(superTraitDef.getAllSuperTypeNames()).thenReturn(superSuperTypeNames); - EntityNotificationImpl entityNotification = - new EntityNotificationImpl(entity, EntityNotification.OperationType.TRAIT_ADD, typeSystem); + EntityNotificationImpl entityNotification = + new EntityNotificationImpl(entity, EntityNotification.OperationType.TRAIT_ADD, typeSystem); - List<IStruct> allTraits = entityNotification.getAllTraits(); + List<IStruct> allTraits = entityNotification.getAllTraits(); - assertEquals(2, allTraits.size()); + assertEquals(2, allTraits.size()); - for (IStruct trait : allTraits) { - String typeName = trait.getTypeName(); - assertTrue(typeName.equals(traitName) || typeName.equals(superTraitName)); + for (IStruct trait : allTraits) { + String typeName = trait.getTypeName(); + assertTrue(typeName.equals(traitName) || typeName.equals(superTraitName)); + } } - } - @Test - public void testEquals() throws Exception { - Referenceable entity = getEntity("id"); + @Test + public void testEquals() throws Exception { + Referenceable entity = getEntity("id"); - EntityNotificationImpl entityNotification2 = - new EntityNotificationImpl(entity, EntityNotification.OperationType.ENTITY_CREATE, - Collections.<IStruct>emptyList()); + EntityNotificationImpl entityNotification2 = + new EntityNotificationImpl(entity, EntityNotification.OperationType.ENTITY_CREATE, + Collections.<IStruct>emptyList()); - EntityNotificationImpl entityNotification = - new EntityNotificationImpl(entity, EntityNotification.OperationType.ENTITY_CREATE, - Collections.<IStruct>emptyList()); + EntityNotificationImpl entityNotification = + new EntityNotificationImpl(entity, EntityNotification.OperationType.ENTITY_CREATE, + Collections.<IStruct>emptyList()); - assertTrue(entityNotification.equals(entityNotification2)); - assertTrue(entityNotification2.equals(entityNotification)); - } + assertTrue(entityNotification.equals(entityNotification2)); + assertTrue(entityNotification2.equals(entityNotification)); + } - private Referenceable getEntity(String id, IStruct ... traits) { - String typeName = "typeName"; - Map<String, Object> values = new HashMap<>(); + private Referenceable getEntity(String id, IStruct... traits) { + String typeName = "typeName"; + Map<String, Object> values = new HashMap<>(); - List<String> traitNames = new LinkedList<>(); - Map<String, IStruct> traitMap = new HashMap<>(); + List<String> traitNames = new LinkedList<>(); + Map<String, IStruct> traitMap = new HashMap<>(); - for (IStruct trait : traits) { - String traitName = trait.getTypeName(); + for (IStruct trait : traits) { + String traitName = trait.getTypeName(); - traitNames.add(traitName); - traitMap.put(traitName, trait); + traitNames.add(traitName); + traitMap.put(traitName, trait); + } + return new Referenceable(id, typeName, values, traitNames, traitMap); } - return new Referenceable(id, typeName, values, traitNames, traitMap); - } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c0b4975b/release-log.txt ---------------------------------------------------------------------- diff --git a/release-log.txt b/release-log.txt index 3e0ee9c..c17579c 100644 --- a/release-log.txt +++ b/release-log.txt @@ -9,6 +9,7 @@ ATLAS-54 Rename configs in hive hook (shwethags) ATLAS-3 Mixed Index creation fails with Date types (sumasai via shwethags) ALL CHANGES: +ATLAS-300 Need additional integration test coverage for entity notifications (tbeerbower via shwethags) ATLAS-304 surefire fails to run tests if maven project directory path has embedded space(dkantor via sumasai) ATLAS-301 Atlas Distribution module test is failing (yhemanth via shwethags) ATLAS-114 Upgrade hbase client to 1.1.2 (sumasai) http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c0b4975b/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationIT.java ---------------------------------------------------------------------- diff --git a/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationIT.java b/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationIT.java index 204b95a..6929961 100644 --- a/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationIT.java +++ b/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationIT.java @@ -18,84 +18,293 @@ package org.apache.atlas.notification; +import com.google.common.collect.ImmutableList; import com.google.inject.Inject; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; import org.apache.atlas.notification.entity.EntityNotification; +import org.apache.atlas.typesystem.IReferenceableInstance; +import org.apache.atlas.typesystem.IStruct; import org.apache.atlas.typesystem.Referenceable; +import org.apache.atlas.typesystem.Struct; +import org.apache.atlas.typesystem.json.InstanceSerialization; +import org.apache.atlas.typesystem.json.TypesSerialization$; +import org.apache.atlas.typesystem.persistence.Id; +import org.apache.atlas.typesystem.types.HierarchicalTypeDefinition; +import org.apache.atlas.typesystem.types.TraitType; +import org.apache.atlas.typesystem.types.utils.TypesUtil; import org.apache.atlas.web.resources.BaseResourceIT; +import org.apache.atlas.web.util.Servlets; +import org.junit.AfterClass; import org.testng.Assert; import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.Guice; import org.testng.annotations.Test; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.Response; +import java.util.Collections; +import java.util.LinkedList; import java.util.List; +import static org.testng.Assert.*; + /** * Entity Notification Integration Tests. */ @Guice(modules = NotificationModule.class) public class EntityNotificationIT extends BaseResourceIT { - @Inject - private NotificationInterface notificationInterface; + private static final String ENTITIES = "api/atlas/entities"; + private static final String TRAITS = "traits"; + private static final int MAX_WAIT_TIME = 10000; + private final String DATABASE_NAME = "db" + randomString(); + private final String TABLE_NAME = "table" + randomString(); + @Inject + private NotificationInterface notificationInterface; + private EntityNotificationConsumer notificationConsumer; + private Id tableId; + private String traitName; + + @BeforeClass + public void setUp() throws Exception { + super.setUp(); + createTypeDefinitions(); + + List<NotificationConsumer<EntityNotification>> consumers = + notificationInterface.createConsumers(NotificationInterface.NotificationType.ENTITIES, 1); + + NotificationConsumer<EntityNotification> consumer = consumers.iterator().next(); + notificationConsumer = new EntityNotificationConsumer(consumer); + notificationConsumer.start(); + } + + @AfterClass + public void tearDown() { + notificationConsumer.stop(); + } + + @BeforeMethod + public void setupTest() { + notificationConsumer.reset(); + } + + @Test + public void testCreateEntity() throws Exception { + Referenceable tableInstance = createHiveTableInstance(DATABASE_NAME, TABLE_NAME); + + tableId = createInstance(tableInstance); + + final String guid = tableId._getId(); - @BeforeClass - public void setUp() throws Exception { - super.setUp(); - createTypeDefinitions(); - } + waitForNotification(MAX_WAIT_TIME); - @Test - public void testEntityNotification() throws Exception { + EntityNotification entityNotification = notificationConsumer.getLastEntityNotification(); - List<NotificationConsumer<EntityNotification>> consumers = - notificationInterface.createConsumers(NotificationInterface.NotificationType.ENTITIES, 1); + assertNotNull(entityNotification); + assertEquals(EntityNotification.OperationType.ENTITY_CREATE, entityNotification.getOperationType()); - NotificationConsumer<EntityNotification> consumer = consumers.iterator().next(); - final EntityNotificationConsumer notificationConsumer = new EntityNotificationConsumer(consumer); - Thread thread = new Thread(notificationConsumer); - thread.start(); + IReferenceableInstance entity = entityNotification.getEntity(); + + assertEquals(HIVE_TABLE_TYPE, entity.getTypeName()); + assertEquals(guid, entity.getId()._getId()); + } - createEntity("Sales", "Sales Database", "John ETL", "hdfs://host:8000/apps/warehouse/sales"); + @Test(dependsOnMethods = "testCreateEntity") + public void testUpdateEntity() throws Exception { + final String property = "description"; + final String newValue = "New description!"; - waitFor(10000, new Predicate() { - @Override - public boolean evaluate() throws Exception { - return notificationConsumer.entityNotification != null; - } - }); + final String guid = tableId._getId(); - Assert.assertNotNull(notificationConsumer.entityNotification); - Assert.assertEquals(EntityNotification.OperationType.ENTITY_CREATE, notificationConsumer.entityNotification.getOperationType()); - Assert.assertEquals(DATABASE_TYPE, notificationConsumer.entityNotification.getEntity().getTypeName()); - Assert.assertEquals("Sales", notificationConsumer.entityNotification.getEntity().get("name")); - } + serviceClient.updateEntity(guid, property, newValue); - private void createEntity(String name, String description, String owner, String locationUri, String... traitNames) - throws Exception { + waitForNotification(MAX_WAIT_TIME); - Referenceable referenceable = new Referenceable(DATABASE_TYPE, traitNames); - referenceable.set("name", name); - referenceable.set("description", description); - referenceable.set("owner", owner); - referenceable.set("locationUri", locationUri); - referenceable.set("createTime", System.currentTimeMillis()); + EntityNotification entityNotification = notificationConsumer.getLastEntityNotification(); - createInstance(referenceable); - } + assertNotNull(entityNotification); + assertEquals(EntityNotification.OperationType.ENTITY_UPDATE, entityNotification.getOperationType()); - private static class EntityNotificationConsumer implements Runnable { - private final NotificationConsumer<EntityNotification> consumerIterator; - private EntityNotification entityNotification = null; + IReferenceableInstance entity = entityNotification.getEntity(); - public EntityNotificationConsumer(NotificationConsumer<EntityNotification> consumerIterator) { - this.consumerIterator = consumerIterator; + assertEquals(HIVE_TABLE_TYPE, entity.getTypeName()); + assertEquals(guid, entity.getId()._getId()); + + assertEquals(newValue, entity.getValuesMap().get(property)); } - @Override - public void run() { - while(consumerIterator.hasNext()) { - entityNotification = consumerIterator.next(); - } + @Test(dependsOnMethods = "testCreateEntity") + public void testAddTrait() throws Exception { + String superSuperTraitName = "SuperTrait" + randomString(); + createTrait(superSuperTraitName); + + String superTraitName = "SuperTrait" + randomString(); + createTrait(superTraitName, superSuperTraitName); + + traitName = "Trait" + randomString(); + createTrait(traitName, superTraitName); + + Struct traitInstance = new Struct(traitName); + String traitInstanceJSON = InstanceSerialization.toJson(traitInstance, true); + LOG.debug("Trait instance = " + traitInstanceJSON); + + final String guid = tableId._getId(); + + ClientResponse clientResponse = addTrait(guid, traitInstanceJSON); + assertEquals(clientResponse.getStatus(), Response.Status.CREATED.getStatusCode()); + + waitForNotification(MAX_WAIT_TIME); + + EntityNotification entityNotification = notificationConsumer.getLastEntityNotification(); + + assertNotNull(entityNotification); + assertEquals(EntityNotification.OperationType.TRAIT_ADD, entityNotification.getOperationType()); + + IReferenceableInstance entity = entityNotification.getEntity(); + + assertEquals(HIVE_TABLE_TYPE, entity.getTypeName()); + assertEquals(guid, entity.getId()._getId()); + + assertTrue(entity.getTraits().contains(traitName)); + + List<IStruct> allTraits = entityNotification.getAllTraits(); + List<String> allTraitNames = new LinkedList<>(); + + for (IStruct struct : allTraits) { + allTraitNames.add(struct.getTypeName()); + } + assertTrue(allTraitNames.contains(traitName)); + assertTrue(allTraitNames.contains(superTraitName)); + assertTrue(allTraitNames.contains(superSuperTraitName)); + + // add another trait with the same super type to the entity + notificationConsumer.reset(); + + String anotherTraitName = "Trait" + randomString(); + createTrait(anotherTraitName, superTraitName); + + traitInstance = new Struct(anotherTraitName); + traitInstanceJSON = InstanceSerialization.toJson(traitInstance, true); + LOG.debug("Trait instance = " + traitInstanceJSON); + + clientResponse = addTrait(guid, traitInstanceJSON); + assertEquals(clientResponse.getStatus(), Response.Status.CREATED.getStatusCode()); + + waitForNotification(MAX_WAIT_TIME); + + entityNotification = notificationConsumer.getLastEntityNotification(); + + assertNotNull(entityNotification); + assertEquals(EntityNotification.OperationType.TRAIT_ADD, entityNotification.getOperationType()); + + allTraits = entityNotification.getAllTraits(); + allTraitNames = new LinkedList<>(); + + for (IStruct struct : allTraits) { + allTraitNames.add(struct.getTypeName()); + } + assertTrue(allTraitNames.contains(traitName)); + assertTrue(allTraitNames.contains(anotherTraitName)); + // verify that the super type shows up twice in all traits + assertEquals(2, Collections.frequency(allTraitNames, superTraitName)); + } + + @Test(dependsOnMethods = "testAddTrait") + public void testDeleteTrait() throws Exception { + final String guid = tableId._getId(); + + ClientResponse clientResponse = deleteTrait(guid, traitName); + Assert.assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode()); + + waitForNotification(MAX_WAIT_TIME); + + EntityNotification entityNotification = notificationConsumer.getLastEntityNotification(); + + assertNotNull(entityNotification); + assertEquals(EntityNotification.OperationType.TRAIT_DELETE, + entityNotification.getOperationType()); + + IReferenceableInstance entity = entityNotification.getEntity(); + + assertEquals(HIVE_TABLE_TYPE, entity.getTypeName()); + assertEquals(guid, entity.getId()._getId()); + + assertFalse(entity.getTraits().contains(traitName)); + } + + + // ----- helper methods --------------------------------------------------- + + private void createTrait(String traitName, String ... superTraitNames) throws Exception { + HierarchicalTypeDefinition<TraitType> trait = + TypesUtil.createTraitTypeDef(traitName, ImmutableList.copyOf(superTraitNames)); + + String traitDefinitionJSON = TypesSerialization$.MODULE$.toJson(trait, true); + LOG.debug("Trait definition = " + traitDefinitionJSON); + createType(traitDefinitionJSON); + } + + private ClientResponse addTrait(String guid, String traitInstance) { + WebResource resource = service.path(ENTITIES).path(guid).path(TRAITS); + + return resource.accept(Servlets.JSON_MEDIA_TYPE) + .type(Servlets.JSON_MEDIA_TYPE) + .method(HttpMethod.POST, ClientResponse.class, traitInstance); + } + + private ClientResponse deleteTrait(String guid, String traitName) { + WebResource resource = service.path(ENTITIES).path(guid).path(TRAITS).path(traitName); + + return resource.accept(Servlets.JSON_MEDIA_TYPE).type(Servlets.JSON_MEDIA_TYPE) + .method(HttpMethod.DELETE, ClientResponse.class); + } + + private void waitForNotification(int maxWait) throws Exception { + waitFor(maxWait, new Predicate() { + @Override + public boolean evaluate() throws Exception { + return notificationConsumer.getLastEntityNotification() != null; + } + }); + } + + + // ----- inner class : EntityNotificationConsumer -------------------------- + + private static class EntityNotificationConsumer implements Runnable { + private final NotificationConsumer<EntityNotification> consumerIterator; + private EntityNotification entityNotification = null; + private boolean run; + + public EntityNotificationConsumer(NotificationConsumer<EntityNotification> consumerIterator) { + this.consumerIterator = consumerIterator; + } + + @Override + public void run() { + while (run && consumerIterator.hasNext()) { + entityNotification = consumerIterator.next(); + } + } + + public void reset() { + entityNotification = null; + } + + public void start() { + Thread thread = new Thread(this); + run = true; + thread.start(); + } + + public void stop() { + run = false; + } + + public EntityNotification getLastEntityNotification() { + return entityNotification; + } } - } }
