Java tutorial
/** * 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.service; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import org.apache.atlas.AtlasClient; import org.apache.atlas.AtlasException; import org.apache.atlas.EntityAuditEvent; import org.apache.atlas.RequestContext; import org.apache.atlas.TestOnlyModule; import org.apache.atlas.TestUtils; import org.apache.atlas.discovery.graph.GraphBackedDiscoveryService; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.listener.ChangedTypeDefs; import org.apache.atlas.listener.EntityChangeListener; import org.apache.atlas.listener.TypeDefChangeListener; import org.apache.atlas.query.QueryParams; import org.apache.atlas.repository.audit.EntityAuditRepository; import org.apache.atlas.repository.audit.HBaseBasedAuditRepository; import org.apache.atlas.repository.audit.HBaseTestUtils; import org.apache.atlas.repository.graph.AtlasGraphProvider; import org.apache.atlas.services.DefaultMetadataService; import org.apache.atlas.services.MetadataService; import org.apache.atlas.type.AtlasTypeUtil; import org.apache.atlas.typesystem.IReferenceableInstance; import org.apache.atlas.typesystem.IStruct; import org.apache.atlas.typesystem.ITypedReferenceableInstance; import org.apache.atlas.typesystem.Referenceable; import org.apache.atlas.typesystem.Struct; import org.apache.atlas.typesystem.TypesDef; import org.apache.atlas.typesystem.exception.EntityNotFoundException; import org.apache.atlas.typesystem.exception.TypeNotFoundException; import org.apache.atlas.typesystem.json.InstanceSerialization; import org.apache.atlas.typesystem.json.TypesSerialization; import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.typesystem.types.AttributeDefinition; import org.apache.atlas.typesystem.types.ClassType; import org.apache.atlas.typesystem.types.DataTypes; import org.apache.atlas.typesystem.types.EnumValue; import org.apache.atlas.typesystem.types.HierarchicalTypeDefinition; import org.apache.atlas.typesystem.types.Multiplicity; import org.apache.atlas.typesystem.types.TypeSystem; import org.apache.atlas.typesystem.types.ValueConversionException; import org.apache.atlas.typesystem.types.cache.TypeCache; import org.apache.atlas.typesystem.types.utils.TypesUtil; import org.apache.atlas.utils.ParamChecker; import org.apache.commons.lang.RandomStringUtils; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.testng.Assert; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Guice; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.apache.atlas.TestUtils.*; import static org.apache.atlas.typesystem.types.utils.TypesUtil.createClassTypeDef; import static org.apache.atlas.typesystem.types.utils.TypesUtil.createOptionalAttrDef; import static org.testng.Assert.*; @Guice(modules = TestOnlyModule.class) public class DefaultMetadataServiceTest { @Inject private MetadataService metadataService; private TypeDefChangeListener typeDefChangeListener; @Inject private EntityAuditRepository auditRepository; @Inject private GraphBackedDiscoveryService discoveryService; private Referenceable db = createDBEntity(); private Referenceable table; private Id tableId; private final String NAME = "name"; @BeforeTest public void setUp() throws Exception { typeDefChangeListener = (DefaultMetadataService) metadataService; metadataService = TestUtils.addSessionCleanupWrapper(metadataService); if (auditRepository instanceof HBaseBasedAuditRepository) { HBaseTestUtils.startCluster(); ((HBaseBasedAuditRepository) auditRepository).start(); } TestUtils.resetRequestContext(); RequestContext.get().setUser("testuser"); TypesDef typesDef = TestUtils.defineHiveTypes(); try { metadataService.getTypeDefinition(TestUtils.TABLE_TYPE); } catch (TypeNotFoundException e) { metadataService.createType(TypesSerialization.toJson(typesDef)); } String dbGUid = TestUtils.createInstance(metadataService, db); table = createTableEntity(dbGUid); String tableGuid = TestUtils.createInstance(metadataService, table); String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); table = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); tableId = new Id(tableGuid, 0, TestUtils.TABLE_TYPE); } @AfterTest public void shutdown() throws Exception { try { TypeSystem.getInstance().reset(); if (auditRepository instanceof HBaseBasedAuditRepository) { ((HBaseBasedAuditRepository) auditRepository).stop(); HBaseTestUtils.stopCluster(); } } finally { AtlasGraphProvider.cleanup(); } } private AtlasClient.EntityResult updateInstance(Referenceable entity) throws Exception { RequestContext.createContext(); ParamChecker.notNull(entity, "Entity"); ParamChecker.notNull(entity.getId(), "Entity"); String entityjson = InstanceSerialization.toJson(entity, true); JSONArray entitiesJson = new JSONArray(); entitiesJson.put(entityjson); return metadataService.updateEntities(entitiesJson.toString()).getEntityResult(); } @Test(expectedExceptions = TypeNotFoundException.class) public void testCreateEntityWithUnknownDatatype() throws Exception { Referenceable entity = new Referenceable("Unknown datatype"); String dbName = RandomStringUtils.randomAlphanumeric(10); entity.set(NAME, dbName); entity.set("description", "us db"); TestUtils.createInstance(metadataService, entity); Assert.fail(TypeNotFoundException.class.getSimpleName() + " was expected but none thrown."); } @Test public void testCreateEntityWithUniqueAttribute() throws Exception { //name is the unique attribute Referenceable entity = createDBEntity(); String id = TestUtils.createInstance(metadataService, entity); assertAuditEvents(id, EntityAuditEvent.EntityAuditAction.ENTITY_CREATE); //using the same name should succeed, but not create another entity String newId = TestUtils.createInstance(metadataService, entity); assertNull(newId); //Same entity, but different qualified name should succeed entity.set(NAME, TestUtils.randomString()); newId = TestUtils.createInstance(metadataService, entity); Assert.assertNotEquals(newId, id); } @Test //Titan doesn't allow some reserved chars in property keys. Verify that atlas encodes these //See GraphHelper.encodePropertyKey() public void testSpecialCharacters() throws Exception { //Verify that type can be created with reserved characters in typename, attribute name String strAttrName = randomStrWithReservedChars(); String arrayAttrName = randomStrWithReservedChars(); String mapAttrName = randomStrWithReservedChars(); HierarchicalTypeDefinition<ClassType> typeDefinition = createClassTypeDef( "test_type_" + RandomStringUtils.randomAlphanumeric(10), ImmutableSet.<String>of(), createOptionalAttrDef(strAttrName, DataTypes.STRING_TYPE), new AttributeDefinition(arrayAttrName, DataTypes.arrayTypeName(DataTypes.STRING_TYPE.getName()), Multiplicity.OPTIONAL, false, null), new AttributeDefinition(mapAttrName, DataTypes.mapTypeName(DataTypes.STRING_TYPE.getName(), DataTypes.STRING_TYPE.getName()), Multiplicity.OPTIONAL, false, null)); metadataService.createType(TypesSerialization.toJson(typeDefinition, false)); //verify that entity can be created with reserved characters in string value, array value and map key and value Referenceable entity = new Referenceable(typeDefinition.typeName); entity.set(strAttrName, randomStrWithReservedChars()); entity.set(arrayAttrName, new ArrayList<String>() { { add(randomStrWithReservedChars()); } }); entity.set(mapAttrName, new HashMap<String, String>() { { put(randomStrWithReservedChars(), randomStrWithReservedChars()); } }); String id = createInstance(metadataService, entity); //Verify that get entity definition returns actual values with reserved characters Referenceable instance = InstanceSerialization .fromJsonReferenceable(metadataService.getEntityDefinitionJson(id), true); assertReferenceableEquals(instance, entity); //Verify that search with reserved characters works - for string attribute String query = String.format("`%s` where `%s` = '%s'", typeDefinition.typeName, strAttrName, entity.get(strAttrName)); String responseJson = discoveryService.searchByDSL(query, new QueryParams(1, 0)); JSONObject response = new JSONObject(responseJson); assertEquals(response.getJSONArray("rows").length(), 1); } //equals excluding the id private void assertReferenceableEquals(Referenceable actual, Referenceable expected) { List<String> traits = actual.getTraits(); Map<String, IStruct> traitsMap = new HashMap<>(); for (String trait : traits) { traitsMap.put(trait, actual.getTrait(trait)); } Referenceable newActual = new Referenceable(expected.getId(), actual.getTypeName(), actual.getValuesMap(), traits, traitsMap); assertEquals(newActual, expected); } private String randomStrWithReservedChars() { return randomString() + "\"${}%"; } @Test public void testAddDeleteTrait() throws Exception { Referenceable entity = createDBEntity(); String id = TestUtils.createInstance(metadataService, entity); //add trait Struct tag = new Struct(TestUtils.PII); metadataService.addTrait(id, InstanceSerialization.toJson(tag, true)); List<String> traits = metadataService.getTraitNames(id); assertEquals(traits.size(), 1); assertEquals(traits.get(0), PII); //getTrait IStruct traitDefinition = metadataService.getTraitDefinition(id, PII); Assert.assertNotNull(traitDefinition); assertEquals(traitDefinition.getValuesMap().size(), 0); //delete trait metadataService.deleteTrait(id, PII); traits = metadataService.getTraitNames(id); assertEquals(traits.size(), 0); //add trait again metadataService.addTrait(id, InstanceSerialization.toJson(tag, true)); traits = metadataService.getTraitNames(id); assertEquals(traits.size(), 1); assertEquals(traits.get(0), PII); } @Test public void testEntityAudit() throws Exception { //create entity Referenceable entity = createDBEntity(); String id = TestUtils.createInstance(metadataService, entity); assertAuditEvents(id, EntityAuditEvent.EntityAuditAction.ENTITY_CREATE); Struct tag = new Struct(TestUtils.PII); metadataService.addTrait(id, InstanceSerialization.toJson(tag, true)); assertAuditEvents(id, EntityAuditEvent.EntityAuditAction.TAG_ADD); metadataService.deleteTrait(id, TestUtils.PII); assertAuditEvents(id, EntityAuditEvent.EntityAuditAction.TAG_DELETE); metadataService.updateEntityAttributeByGuid(id, "description", "new description"); assertAuditEvents(id, EntityAuditEvent.EntityAuditAction.ENTITY_UPDATE); metadataService.deleteEntities(Arrays.asList(id)); assertAuditEvents(id, EntityAuditEvent.EntityAuditAction.ENTITY_DELETE); } private AtlasClient.EntityResult deleteEntities(String... guids) throws AtlasException { RequestContext.createContext(); return metadataService.deleteEntities(Arrays.asList(guids)); } private void assertAuditEvents(String id, EntityAuditEvent.EntityAuditAction expectedAction) throws Exception { List<EntityAuditEvent> events = auditRepository.listEvents(id, null, (short) 10); for (EntityAuditEvent event : events) { if (event.getAction() == expectedAction) { return; } } fail("Expected audit action " + expectedAction); } private void assertAuditEvents(String entityId, int numEvents) throws Exception { List<EntityAuditEvent> events = metadataService.getAuditEvents(entityId, null, (short) numEvents); assertNotNull(events); assertEquals(events.size(), numEvents); } @Test public void testCreateEntityWithUniqueAttributeWithReference() throws Exception { Referenceable db = createDBEntity(); String dbId = TestUtils.createInstance(metadataService, db); //Assert that there is just 1 audit events and thats for entity create assertAuditEvents(dbId, 1); assertAuditEvents(dbId, EntityAuditEvent.EntityAuditAction.ENTITY_CREATE); Referenceable table = new Referenceable(TestUtils.TABLE_TYPE); table.set(NAME, TestUtils.randomString()); table.set("description", "random table"); table.set("type", "type"); table.set("tableType", "MANAGED"); table.set("database", new Id(dbId, 0, TestUtils.DATABASE_TYPE)); table.set("databaseComposite", db); TestUtils.createInstance(metadataService, table); //table create should re-use the db instance created earlier String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Referenceable actualDb = (Referenceable) tableDefinition.get("databaseComposite"); assertEquals(actualDb.getId().id, dbId); //Assert that as part table create, db is not created and audit event is not added to db assertAuditEvents(dbId, 1); } @Test public void testUpdateEntityByUniqueAttribute() throws Exception { final List<String> colNameList = ImmutableList.of("col1", "col2"); Referenceable tableUpdated = new Referenceable(TestUtils.TABLE_TYPE, new HashMap<String, Object>() { { put("columnNames", colNameList); } }); metadataService.updateEntityByUniqueAttribute(table.getTypeName(), NAME, (String) table.get(NAME), tableUpdated); String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); List<String> actualColumns = (List) tableDefinition.get("columnNames"); assertEquals(actualColumns, colNameList); } @Test public void testUpdateEntityWithMap() throws Exception { final Map<String, Struct> partsMap = new HashMap<>(); partsMap.put("part0", new Struct(TestUtils.PARTITION_STRUCT_TYPE, new HashMap<String, Object>() { { put(NAME, "test"); } })); table.set("partitionsMap", partsMap); updateInstance(table); String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Assert.assertTrue(partsMap.get("part0") .equalsContents(((Map<String, Struct>) tableDefinition.get("partitionsMap")).get("part0"))); //update map - add a map key partsMap.put("part1", new Struct(TestUtils.PARTITION_STRUCT_TYPE, new HashMap<String, Object>() { { put(NAME, "test1"); } })); table.set("partitionsMap", partsMap); updateInstance(table); tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); assertEquals(((Map<String, Struct>) tableDefinition.get("partitionsMap")).size(), 2); Assert.assertTrue(partsMap.get("part1") .equalsContents(((Map<String, Struct>) tableDefinition.get("partitionsMap")).get("part1"))); //update map - remove a key and add another key partsMap.remove("part0"); partsMap.put("part2", new Struct(TestUtils.PARTITION_STRUCT_TYPE, new HashMap<String, Object>() { { put(NAME, "test2"); } })); table.set("partitionsMap", partsMap); updateInstance(table); tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); assertEquals(((Map<String, Struct>) tableDefinition.get("partitionsMap")).size(), 2); Assert.assertNull(((Map<String, Struct>) tableDefinition.get("partitionsMap")).get("part0")); Assert.assertTrue(partsMap.get("part2") .equalsContents(((Map<String, Struct>) tableDefinition.get("partitionsMap")).get("part2"))); //update struct value for existing map key Struct partition2 = partsMap.get("part2"); partition2.set(NAME, "test2Updated"); updateInstance(table); tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); assertEquals(((Map<String, Struct>) tableDefinition.get("partitionsMap")).size(), 2); Assert.assertNull(((Map<String, Struct>) tableDefinition.get("partitionsMap")).get("part0")); Assert.assertTrue(partsMap.get("part2") .equalsContents(((Map<String, Struct>) tableDefinition.get("partitionsMap")).get("part2"))); //Test map pointing to a class final Map<String, Referenceable> columnsMap = new HashMap<>(); Referenceable col0Type = new Referenceable(TestUtils.COLUMN_TYPE, new HashMap<String, Object>() { { put(NAME, "test1"); put("type", "string"); } }); columnsMap.put("col0", col0Type); Referenceable col1Type = new Referenceable(TestUtils.COLUMN_TYPE, new HashMap<String, Object>() { { put(NAME, "test2"); put("type", "string"); } }); columnsMap.put("col1", col1Type); table.set(TestUtils.COLUMNS_MAP, columnsMap); updateInstance(table); verifyMapUpdates(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME), columnsMap, TestUtils.COLUMNS_MAP); //Swap elements columnsMap.clear(); columnsMap.put("col0", col1Type); columnsMap.put("col1", col0Type); table.set(TestUtils.COLUMNS_MAP, columnsMap); updateInstance(table); verifyMapUpdates(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME), columnsMap, TestUtils.COLUMNS_MAP); //Drop the first key and change the class type as well to col0 columnsMap.clear(); columnsMap.put("col0", col0Type); table.set(TestUtils.COLUMNS_MAP, columnsMap); updateInstance(table); verifyMapUpdates(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME), columnsMap, TestUtils.COLUMNS_MAP); //Clear state table.setNull(TestUtils.COLUMNS_MAP); updateInstance(table); verifyMapUpdates(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME), null, TestUtils.COLUMNS_MAP); } private void verifyMapUpdates(String typeName, String uniqAttrName, String uniqAttrValue, Map<String, Referenceable> expectedMap, String mapAttrName) throws AtlasException { String json = metadataService.getEntityDefinition(typeName, uniqAttrName, uniqAttrValue); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(json, true); Map<String, Referenceable> actualMap = (Map<String, Referenceable>) tableDefinition.get(mapAttrName); if (expectedMap == null && actualMap != null) { //all are marked as deleted in case of soft delete for (String key : actualMap.keySet()) { assertEquals(actualMap.get(key).getId().state, Id.EntityState.DELETED); } } else if (expectedMap == null) { //hard delete case assertNull(actualMap); } else { assertTrue(actualMap.size() >= expectedMap.size()); for (String key : expectedMap.keySet()) { assertTrue(actualMap.get(key).equalsContents(expectedMap.get(key))); } //rest of the keys are marked as deleted List<String> extraKeys = new ArrayList<>(actualMap.keySet()); extraKeys.removeAll(expectedMap.keySet()); for (String key : extraKeys) { assertEquals(actualMap.get(key).getId().getState(), Id.EntityState.DELETED); } } } @Test public void testUpdateEntityAddAndUpdateArrayAttr() throws Exception { //Update entity, add new array attribute //add array of primitives final List<String> colNameList = ImmutableList.of("col1", "col2"); Referenceable tableUpdated = new Referenceable(TestUtils.TABLE_TYPE, new HashMap<String, Object>() { { put("columnNames", colNameList); } }); metadataService.updateEntityPartialByGuid(tableId._getId(), tableUpdated); String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); List<String> actualColumns = (List) tableDefinition.get("columnNames"); assertEquals(actualColumns, colNameList); //update array of primitives final List<String> updatedColNameList = ImmutableList.of("col2", "col3"); tableUpdated = new Referenceable(TestUtils.TABLE_TYPE, new HashMap<String, Object>() { { put("columnNames", updatedColNameList); } }); metadataService.updateEntityPartialByGuid(tableId.getId()._getId(), tableUpdated); tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); actualColumns = (List) tableDefinition.get("columnNames"); assertEquals(actualColumns, updatedColNameList); } private AtlasClient.EntityResult updateEntityPartial(String guid, Referenceable entity) throws AtlasException { RequestContext.createContext(); return metadataService.updateEntityPartialByGuid(guid, entity).getEntityResult(); } @Test public void testUpdateEntityArrayOfClass() throws Exception { //test array of class with id final List<Referenceable> columns = new ArrayList<>(); Map<String, Object> values = new HashMap<>(); values.put(NAME, "col1"); values.put("type", "type"); Referenceable col1 = new Referenceable(TestUtils.COLUMN_TYPE, values); columns.add(col1); Referenceable tableUpdated = new Referenceable(TestUtils.TABLE_TYPE, new HashMap<String, Object>() { { put(COLUMNS_ATTR_NAME, columns); } }); AtlasClient.EntityResult entityResult = updateEntityPartial(tableId._getId(), tableUpdated); assertEquals(entityResult.getCreatedEntities().size(), 1); //col1 created assertEquals(entityResult.getUpdateEntities().size(), 1); //table updated assertEquals(entityResult.getUpdateEntities().get(0), tableId._getId()); verifyArrayUpdates(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME), columns, COLUMNS_ATTR_NAME); //Partial update. Add col2 But also update col1 Map<String, Object> valuesCol5 = new HashMap<>(); valuesCol5.put(NAME, "col2"); valuesCol5.put("type", "type"); Referenceable col2 = new Referenceable(TestUtils.COLUMN_TYPE, valuesCol5); //update col1 col1.set("type", "type1"); columns.add(col2); tableUpdated = new Referenceable(TestUtils.TABLE_TYPE, new HashMap<String, Object>() { { put(COLUMNS_ATTR_NAME, columns); } }); entityResult = updateEntityPartial(tableId._getId(), tableUpdated); assertEquals(entityResult.getCreatedEntities().size(), 1); //col2 created assertEquals(entityResult.getUpdateEntities().size(), 2); //table, col1 updated verifyArrayUpdates(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME), columns, COLUMNS_ATTR_NAME); //Complete update. Add array elements - col3,col4 Map<String, Object> values1 = new HashMap<>(); values1.put(NAME, "col3"); values1.put("type", "type"); Referenceable col3 = new Referenceable(TestUtils.COLUMN_TYPE, values1); columns.add(col3); Map<String, Object> values2 = new HashMap<>(); values2.put(NAME, "col4"); values2.put("type", "type"); Referenceable col4 = new Referenceable(TestUtils.COLUMN_TYPE, values2); columns.add(col4); table.set(COLUMNS_ATTR_NAME, columns); entityResult = updateInstance(table); assertEquals(entityResult.getCreatedEntities().size(), 2); //col3, col4 created verifyArrayUpdates(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME), columns, COLUMNS_ATTR_NAME); //Swap elements columns.clear(); columns.add(col4); columns.add(col3); table.set(COLUMNS_ATTR_NAME, columns); entityResult = updateInstance(table); assertEquals(entityResult.getDeletedEntities().size(), 2); //col1, col2 are deleted verifyArrayUpdates(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME), columns, COLUMNS_ATTR_NAME); //drop a single column columns.clear(); columns.add(col3); table.set(COLUMNS_ATTR_NAME, columns); entityResult = updateInstance(table); assertEquals(entityResult.getDeletedEntities().size(), 1); //col4 deleted verifyArrayUpdates(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME), columns, COLUMNS_ATTR_NAME); //Remove a class reference/Id and insert another reference //Also covers isComposite case since columns is a composite values.clear(); columns.clear(); values.put(NAME, "col5"); values.put("type", "type"); Referenceable col5 = new Referenceable(TestUtils.COLUMN_TYPE, values); columns.add(col5); table.set(COLUMNS_ATTR_NAME, columns); entityResult = updateInstance(table); assertEquals(entityResult.getCreatedEntities().size(), 1); //col5 created assertEquals(entityResult.getDeletedEntities().size(), 1); //col3 deleted verifyArrayUpdates(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME), columns, COLUMNS_ATTR_NAME); //Update array column to null table.setNull(COLUMNS_ATTR_NAME); entityResult = updateInstance(table); assertEquals(entityResult.getDeletedEntities().size(), 1); verifyArrayUpdates(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME), null, COLUMNS_ATTR_NAME); } private void verifyArrayUpdates(String typeName, String uniqAttrName, String uniqAttrValue, List<Referenceable> expectedArray, String arrAttrName) throws AtlasException { String json = metadataService.getEntityDefinition(typeName, uniqAttrName, uniqAttrValue); Referenceable entityDefinition = InstanceSerialization.fromJsonReferenceable(json, true); List<Referenceable> actualArray = (List<Referenceable>) entityDefinition.get(arrAttrName); if (expectedArray == null && actualArray != null) { //all are marked as deleted in case of soft delete for (Referenceable referenceable : actualArray) { assertEquals(referenceable.getId().state, Id.EntityState.DELETED); } } else if (expectedArray == null) { //hard delete case assertNull(actualArray); } else { int index; for (index = 0; index < expectedArray.size(); index++) { Assert.assertTrue(actualArray.get(index).equalsContents(expectedArray.get(index))); } //Rest of the entities in the list are marked as deleted for (; index < actualArray.size(); index++) { assertEquals(actualArray.get(index).getId().state, Id.EntityState.DELETED); } } } @Test public void testStructs() throws Exception { Struct serdeInstance = new Struct(TestUtils.SERDE_TYPE); serdeInstance.set(NAME, "serde1Name"); serdeInstance.set("serde", "test"); serdeInstance.set("description", "testDesc"); table.set("serde1", serdeInstance); String newtableId = updateInstance(table).getUpdateEntities().get(0); assertEquals(newtableId, tableId._getId()); String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Assert.assertNotNull(tableDefinition.get("serde1")); Assert.assertTrue(serdeInstance.equalsContents(tableDefinition.get("serde1"))); //update struct attribute serdeInstance.set("serde", "testUpdated"); updateInstance(table); tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Assert.assertTrue(serdeInstance.equalsContents(tableDefinition.get("serde1"))); //set to null serdeInstance.setNull("description"); updateInstance(table); tableDefinitionJson = metadataService.getEntityDefinitionJson(tableId._getId()); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Assert.assertNull(((Struct) tableDefinition.get("serde1")).get("description")); } @Test public void testCreateEntityWithReferenceableHavingIdNoValue() throws Exception { //ATLAS-383 Test Referenceable sdReferenceable = new Referenceable(TestUtils.STORAGE_DESC_TYPE); sdReferenceable.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, TestUtils.randomString()); sdReferenceable.set("compressed", "false"); sdReferenceable.set("location", "hdfs://tmp/hive-user"); String sdGuid = TestUtils.createInstance(metadataService, sdReferenceable); Referenceable sdRef2 = new Referenceable(sdGuid, TestUtils.STORAGE_DESC_TYPE, null); Referenceable partRef = new Referenceable(TestUtils.PARTITION_CLASS_TYPE); partRef.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, "part-unique"); partRef.set("values", ImmutableList.of("2014-10-01")); partRef.set("table", table); partRef.set("sd", sdRef2); String partGuid = TestUtils.createInstance(metadataService, partRef); Assert.assertNotNull(partGuid); } @Test public void testClassUpdate() throws Exception { //Create new db instance final Referenceable databaseInstance = new Referenceable(TestUtils.DATABASE_TYPE); databaseInstance.set(NAME, TestUtils.randomString()); databaseInstance.set("description", "new database"); String dbId = TestUtils.createInstance(metadataService, databaseInstance); /*Update reference property with Id */ metadataService.updateEntityAttributeByGuid(tableId._getId(), "database", dbId); String tableDefinitionJson = metadataService.getEntityDefinitionJson(tableId._getId()); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); assertEquals(dbId, (((Id) tableDefinition.get("database"))._getId())); /* Update with referenceable - TODO - Fails . Need to fix this */ /*final String dbName = TestUtils.randomString(); final Referenceable databaseInstance2 = new Referenceable(TestUtils.DATABASE_TYPE); databaseInstance2.set(NAME, dbName); databaseInstance2.set("description", "new database 2"); Referenceable updateTable = new Referenceable(TestUtils.TABLE_TYPE, new HashMap<String, Object>() {{ put("database", databaseInstance2); }}); metadataService.updateEntityAttributeByGuid(tableId._getId(), updateTable); tableDefinitionJson = metadataService.getEntityDefinition(tableId._getId()); Referenceable tableDefinitionActual = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); String dbDefJson = metadataService.getEntityDefinition(TestUtils.DATABASE_TYPE, NAME, dbName); Referenceable dbDef = InstanceSerialization.fromJsonReferenceable(dbDefJson, true); Assert.assertNotEquals(dbId, (((Id) tableDefinitionActual.get("database"))._getId())); Assert.assertEquals(dbDef.getObjectId()._getId(), (((Id) tableDefinitionActual.get("database"))._getId())); */ } @Test public void testArrayOfStructs() throws Exception { //Add array of structs TestUtils.dumpGraph(TestUtils.getGraph()); final Struct partition1 = new Struct(TestUtils.PARTITION_STRUCT_TYPE); partition1.set(NAME, "part1"); final Struct partition2 = new Struct(TestUtils.PARTITION_STRUCT_TYPE); partition2.set(NAME, "part2"); List<Struct> partitions = new ArrayList<Struct>() { { add(partition1); add(partition2); } }; table.set("partitions", partitions); String newtableId = updateInstance(table).getUpdateEntities().get(0); assertEquals(newtableId, tableId._getId()); String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Assert.assertNotNull(tableDefinition.get("partitions")); List<Struct> partitionsActual = (List<Struct>) tableDefinition.get("partitions"); assertPartitions(partitionsActual, partitions); //add a new element to array of struct final Struct partition3 = new Struct(TestUtils.PARTITION_STRUCT_TYPE); partition3.set(NAME, "part3"); partitions.add(partition3); table.set("partitions", partitions); newtableId = updateInstance(table).getUpdateEntities().get(0); assertEquals(newtableId, tableId._getId()); tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Assert.assertNotNull(tableDefinition.get("partitions")); partitionsActual = (List<Struct>) tableDefinition.get("partitions"); assertPartitions(partitionsActual, partitions); //remove one of the struct values partitions.remove(1); table.set("partitions", partitions); newtableId = updateInstance(table).getUpdateEntities().get(0); assertEquals(newtableId, tableId._getId()); tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Assert.assertNotNull(tableDefinition.get("partitions")); partitionsActual = (List<Struct>) tableDefinition.get("partitions"); assertPartitions(partitionsActual, partitions); //Update struct value within array of struct partitions.get(0).set(NAME, "part4"); newtableId = updateInstance(table).getUpdateEntities().get(0); assertEquals(newtableId, tableId._getId()); tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Assert.assertNotNull(tableDefinition.get("partitions")); partitionsActual = (List<Struct>) tableDefinition.get("partitions"); assertPartitions(partitionsActual, partitions); //add a repeated element to array of struct final Struct partition4 = new Struct(TestUtils.PARTITION_STRUCT_TYPE); partition4.set(NAME, "part4"); partitions.add(partition4); table.set("partitions", partitions); newtableId = updateInstance(table).getUpdateEntities().get(0); assertEquals(newtableId, tableId._getId()); tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Assert.assertNotNull(tableDefinition.get("partitions")); partitionsActual = (List<Struct>) tableDefinition.get("partitions"); assertPartitions(partitionsActual, partitions); // Remove all elements. Should set array attribute to null partitions.clear(); newtableId = updateInstance(table).getUpdateEntities().get(0); assertEquals(newtableId, tableId._getId()); tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Assert.assertNull(tableDefinition.get("partitions")); } private void assertPartitions(List<Struct> partitionsActual, List<Struct> partitions) { assertEquals(partitionsActual.size(), partitions.size()); for (int index = 0; index < partitions.size(); index++) { assertTrue(partitionsActual.get(index).equalsContents(partitions.get(index))); } } @Test(expectedExceptions = ValueConversionException.class) public void testCreateRequiredAttrNull() throws Exception { //Update required attribute Referenceable tableEntity = new Referenceable(TABLE_TYPE); tableEntity.set(NAME, "table_" + TestUtils.randomString()); TestUtils.createInstance(metadataService, tableEntity); Assert.fail("Expected exception while creating with required attribute null"); } @Test(expectedExceptions = ValueConversionException.class) public void testUpdateRequiredAttrToNull() throws Exception { //Update required attribute String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); assertEquals(tableDefinition.get("description"), "random table"); table.setNull("description"); updateInstance(table); Assert.fail("Expected exception while updating required attribute to null"); } @Test public void testCheckOptionalAttrValueRetention() throws Exception { Referenceable entity = createDBEntity(); String dbId = TestUtils.createInstance(metadataService, entity); entity = getEntity(dbId); //The optional boolean attribute should have a non-null value final String isReplicatedAttr = "isReplicated"; final String paramsAttr = "parameters"; Assert.assertNotNull(entity.get(isReplicatedAttr)); Assert.assertEquals(entity.get(isReplicatedAttr), Boolean.FALSE); Assert.assertNull(entity.get(paramsAttr)); //Update to true entity.set(isReplicatedAttr, Boolean.TRUE); //Update array final HashMap<String, String> params = new HashMap<String, String>() { { put("param1", "val1"); put("param2", "val2"); } }; entity.set(paramsAttr, params); //Complete update updateInstance(entity); entity = getEntity(dbId); Assert.assertNotNull(entity.get(isReplicatedAttr)); Assert.assertEquals(entity.get(isReplicatedAttr), Boolean.TRUE); Assert.assertEquals(entity.get(paramsAttr), params); //Complete update without setting the attribute Referenceable newEntity = createDBEntity(); //Reset name to the current DB name newEntity.set(NAME, entity.get(NAME)); updateInstance(newEntity); entity = getEntity(dbId); Assert.assertNotNull(entity.get(isReplicatedAttr)); Assert.assertEquals(entity.get(isReplicatedAttr), Boolean.TRUE); Assert.assertEquals(entity.get(paramsAttr), params); } private Referenceable getEntity(String guid) throws AtlasException { String entityJson = metadataService.getEntityDefinitionJson(guid); Assert.assertNotNull(entityJson); return InstanceSerialization.fromJsonReferenceable(entityJson, true); } @Test public void testUpdateOptionalAttrToNull() throws Exception { String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); //Update optional Attribute Assert.assertNotNull(tableDefinition.get("created")); //Update optional attribute table.setNull("created"); String newtableId = updateInstance(table).getUpdateEntities().get(0); assertEquals(newtableId, tableId._getId()); tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); Assert.assertNull(tableDefinition.get("created")); } @Test public void testCreateEntityWithEnum() throws Exception { String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table.get(NAME)); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); EnumValue tableType = (EnumValue) tableDefinition.get("tableType"); assertEquals(tableType, new EnumValue("MANAGED", 1)); } @Test public void testGetEntityByUniqueAttribute() throws Exception { Referenceable entity = createDBEntity(); TestUtils.createInstance(metadataService, entity); //get entity by valid qualified name String entityJson = metadataService.getEntityDefinition(TestUtils.DATABASE_TYPE, NAME, (String) entity.get(NAME)); Assert.assertNotNull(entityJson); Referenceable referenceable = InstanceSerialization.fromJsonReferenceable(entityJson, true); assertEquals(referenceable.get(NAME), entity.get(NAME)); //get entity by invalid qualified name try { metadataService.getEntityDefinition(TestUtils.DATABASE_TYPE, NAME, "random"); Assert.fail("Expected EntityNotFoundException"); } catch (EntityNotFoundException e) { //expected } //get entity by non-unique attribute try { metadataService.getEntityDefinition(TestUtils.DATABASE_TYPE, "description", (String) entity.get("description")); Assert.fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { //expected } } @Test public void testDeleteEntities() throws Exception { // Create a table entity, with 3 composite column entities Referenceable dbEntity = createDBEntity(); String dbGuid = TestUtils.createInstance(metadataService, dbEntity); Referenceable table1Entity = createTableEntity(dbGuid); Referenceable col1 = createColumnEntity(); Referenceable col2 = createColumnEntity(); Referenceable col3 = createColumnEntity(); table1Entity.set(COLUMNS_ATTR_NAME, ImmutableList.of(col1, col2, col3)); TestUtils.createInstance(metadataService, table1Entity); // Retrieve the table entities from the repository, // to get their guids and the composite column guids. String entityJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table1Entity.get(NAME)); Assert.assertNotNull(entityJson); table1Entity = InstanceSerialization.fromJsonReferenceable(entityJson, true); List<IReferenceableInstance> table1Columns = (List<IReferenceableInstance>) table1Entity .get(COLUMNS_ATTR_NAME); // Register an EntityChangeListener to verify the notification mechanism // is working for deleteEntities(). EntitiesChangeListener listener = new EntitiesChangeListener(); metadataService.registerListener(listener); //Delete one column String columnId = table1Columns.get(0).getId()._getId(); AtlasClient.EntityResult entityResult = deleteEntities(columnId); //column is deleted and table is updated assertEquals(entityResult.getDeletedEntities().get(0), columnId); assertEquals(entityResult.getUpdateEntities().get(0), table1Entity.getId()._getId()); //verify listener was called for updates and deletes assertEquals(entityResult.getDeletedEntities(), listener.getDeletedEntities()); assertEquals(entityResult.getUpdateEntities(), listener.getUpdatedEntities()); // Delete the table entities. The deletion should cascade // to their composite columns. entityResult = deleteEntities(table1Entity.getId()._getId()); // Verify that deleteEntities() response has guids for tables and their composite columns. Assert.assertTrue(entityResult.getDeletedEntities().contains(table1Entity.getId()._getId())); Assert.assertTrue(entityResult.getDeletedEntities().contains(table1Columns.get(1).getId()._getId())); Assert.assertTrue(entityResult.getDeletedEntities().contains(table1Columns.get(2).getId()._getId())); // Verify that tables and their composite columns have been deleted from the repository. assertEntityDeleted(TABLE_TYPE, NAME, table1Entity.get(NAME)); assertEntityDeleted(COLUMN_TYPE, NAME, col2.get(NAME)); assertEntityDeleted(COLUMN_TYPE, NAME, col3.get(NAME)); // Verify that the listener was notified about the deleted entities. List<String> deletedEntitiesFromListener = listener.getDeletedEntities(); Assert.assertNotNull(deletedEntitiesFromListener); assertEquals(deletedEntitiesFromListener.size(), entityResult.getDeletedEntities().size()); Assert.assertTrue(deletedEntitiesFromListener.containsAll(entityResult.getDeletedEntities())); } private void assertEntityDeleted(String typeName, String attributeName, Object attributeValue) throws AtlasException { try { metadataService.getEntityDefinition(typeName, attributeName, (String) attributeValue); fail("Expected EntityNotFoundException"); } catch (EntityNotFoundException e) { //expected } } @Test public void testDeleteEntityByUniqueAttribute() throws Exception { // Create a table entity, with 3 composite column entities Referenceable dbEntity = createDBEntity(); String dbGuid = TestUtils.createInstance(metadataService, dbEntity); Referenceable table1Entity = createTableEntity(dbGuid); Referenceable col1 = createColumnEntity(); Referenceable col2 = createColumnEntity(); Referenceable col3 = createColumnEntity(); table1Entity.set(COLUMNS_ATTR_NAME, ImmutableList.of(col1, col2, col3)); TestUtils.createInstance(metadataService, table1Entity); // to get their guids and the composite column guids. String entityJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, (String) table1Entity.get(NAME)); Assert.assertNotNull(entityJson); table1Entity = InstanceSerialization.fromJsonReferenceable(entityJson, true); List<IReferenceableInstance> table1Columns = (List<IReferenceableInstance>) table1Entity .get(COLUMNS_ATTR_NAME); // Register an EntityChangeListener to verify the notification mechanism // is working for deleteEntityByUniqueAttribute(). EntitiesChangeListener listener = new EntitiesChangeListener(); metadataService.registerListener(listener); // Delete the table entities. The deletion should cascade // to their composite columns. List<String> deletedGuids = metadataService .deleteEntityByUniqueAttribute(TestUtils.TABLE_TYPE, NAME, (String) table1Entity.get(NAME)) .getDeletedEntities(); // Verify that deleteEntities() response has guids for tables and their composite columns. Assert.assertTrue(deletedGuids.contains(table1Entity.getId()._getId())); for (IReferenceableInstance column : table1Columns) { Assert.assertTrue(deletedGuids.contains(column.getId()._getId())); } // Verify that tables and their composite columns have been deleted from the repository. // Verify that tables and their composite columns have been deleted from the repository. assertEntityDeleted(TABLE_TYPE, NAME, table1Entity.get(NAME)); assertEntityDeleted(COLUMN_TYPE, NAME, col1.get(NAME)); assertEntityDeleted(COLUMN_TYPE, NAME, col2.get(NAME)); assertEntityDeleted(COLUMN_TYPE, NAME, col3.get(NAME)); // Verify that the listener was notified about the deleted entities. List<String> deletedEntitiesFromListener = listener.getDeletedEntities(); Assert.assertNotNull(deletedEntitiesFromListener); assertEquals(deletedEntitiesFromListener.size(), deletedGuids.size()); Assert.assertTrue(deletedEntitiesFromListener.containsAll(deletedGuids)); } @Test public void testTypeUpdateFailureShouldRollBack() throws AtlasException, JSONException { String typeName = "test_type_" + RandomStringUtils.randomAlphanumeric(10); HierarchicalTypeDefinition<ClassType> typeDef = TypesUtil.createClassTypeDef(typeName, ImmutableSet.<String>of(), TypesUtil.createUniqueRequiredAttrDef("test_type_attribute", DataTypes.STRING_TYPE)); TypesDef typesDef = new TypesDef(typeDef, false); JSONObject type = metadataService.createType(TypesSerialization.toJson(typesDef)); Assert.assertNotNull(type.get(AtlasClient.TYPES)); HierarchicalTypeDefinition<ClassType> updatedTypeDef = TypesUtil.createClassTypeDef(typeName, ImmutableSet.<String>of(), TypesUtil.createUniqueRequiredAttrDef("test_type_attribute", DataTypes.STRING_TYPE), TypesUtil.createRequiredAttrDef("test_type_invalid_attribute$", DataTypes.STRING_TYPE)); TypesDef updatedTypesDef = new TypesDef(updatedTypeDef, false); try { metadataService.updateType(TypesSerialization.toJson(updatedTypesDef)); fail("Expected AtlasException"); } catch (AtlasException e) { //expected } //type definition should reflect old type String typeDefinition = metadataService.getTypeDefinition(typeName); typesDef = TypesSerialization.fromJson(typeDefinition); assertEquals(typesDef.classTypes().head().attributeDefinitions.length, 1); } @Test public void testTypeWithDotsCreationShouldNotBeCreated() throws AtlasException, JSONException { String typeName = "test_.v1_type_XXXX"; HierarchicalTypeDefinition<ClassType> typeDef = TypesUtil.createClassTypeDef(typeName, ImmutableSet.<String>of(), TypesUtil.createUniqueRequiredAttrDef("test_type_attribute", DataTypes.STRING_TYPE)); TypesDef typesDef = new TypesDef(typeDef, false); try { metadataService.createType(TypesSerialization.toJson(typesDef)); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertTrue(e.getCause().getMessage().contains(AtlasTypeUtil.getInvalidTypeNameErrorMessage()), e.getCause().getMessage()); } } @Test public void testAuditEventsInvalidParams() throws Exception { //entity id can't be null try { metadataService.getAuditEvents(null, "key", (short) 10); fail("expected IllegalArgumentException"); } catch (IllegalArgumentException e) { //expected IllegalArgumentException assertEquals(e.getMessage(), "entity id cannot be null"); } //entity id can't be empty try { metadataService.getAuditEvents("", "key", (short) 10); fail("expected IllegalArgumentException"); } catch (IllegalArgumentException e) { //expected IllegalArgumentException assertEquals(e.getMessage(), "entity id cannot be empty"); } //start key can be null metadataService.getAuditEvents("id", null, (short) 10); //start key can't be emoty try { metadataService.getAuditEvents("id", "", (short) 10); fail("expected IllegalArgumentException"); } catch (IllegalArgumentException e) { //expected IllegalArgumentException assertEquals(e.getMessage(), "start key cannot be empty"); } //number of results can't be > max value try { metadataService.getAuditEvents("id", "key", (short) 10000); fail("expected IllegalArgumentException"); } catch (IllegalArgumentException e) { //expected IllegalArgumentException assertEquals(e.getMessage(), "count should be <= 1000, current value 10000"); } //number of results can't be <= 0 try { metadataService.getAuditEvents("id", "key", (short) -1); fail("expected IllegalArgumentException"); } catch (IllegalArgumentException e) { //expected IllegalArgumentException assertEquals(e.getMessage(), "count should be > 0, current value -1"); } } @Test public void testOnChangeRefresh() { try { List<String> beforeChangeTypeNames = new ArrayList<>(); beforeChangeTypeNames .addAll(metadataService.getTypeNames(new HashMap<TypeCache.TYPE_FILTER, String>())); typeDefChangeListener.onChange(new ChangedTypeDefs()); List<String> afterChangeTypeNames = new ArrayList<>(); afterChangeTypeNames.addAll(metadataService.getTypeNames(new HashMap<TypeCache.TYPE_FILTER, String>())); Collections.sort(beforeChangeTypeNames); Collections.sort(afterChangeTypeNames); assertEquals(afterChangeTypeNames, beforeChangeTypeNames); } catch (AtlasBaseException e) { fail("Should've succeeded", e); } catch (AtlasException e) { fail("getTypeNames should've succeeded", e); } } private static class EntitiesChangeListener implements EntityChangeListener { private List<String> deletedEntities = new ArrayList<>(); private List<String> updatedEntities = new ArrayList<>(); @Override public void onEntitiesAdded(Collection<ITypedReferenceableInstance> entities, boolean isImport) throws AtlasException { } @Override public void onEntitiesUpdated(Collection<ITypedReferenceableInstance> entities, boolean isImport) throws AtlasException { updatedEntities.clear(); for (ITypedReferenceableInstance entity : entities) { updatedEntities.add(entity.getId()._getId()); } } @Override public void onTraitsAdded(ITypedReferenceableInstance entity, Collection<? extends IStruct> traits) throws AtlasException { } @Override public void onTraitsDeleted(ITypedReferenceableInstance entity, Collection<String> traitNames) throws AtlasException { } @Override public void onTraitsUpdated(ITypedReferenceableInstance entity, Collection<? extends IStruct> traits) throws AtlasException { } @Override public void onEntitiesDeleted(Collection<ITypedReferenceableInstance> entities, boolean isImport) throws AtlasException { deletedEntities.clear(); for (ITypedReferenceableInstance entity : entities) { deletedEntities.add(entity.getId()._getId()); } } public List<String> getDeletedEntities() { return deletedEntities; } public List<String> getUpdatedEntities() { return updatedEntities; } } }