blob: 8c86235e80de9639149acbb06892603eb066a3dd [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.atlas.repository.graph;
import org.apache.atlas.AtlasClient;
import org.apache.atlas.AtlasException;
import org.apache.atlas.TestUtils;
import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.typesystem.IReferenceableInstance;
import org.apache.atlas.typesystem.IStruct;
import org.apache.atlas.typesystem.ITypedReferenceableInstance;
import org.apache.atlas.typesystem.ITypedStruct;
import org.apache.atlas.typesystem.persistence.Id;
import org.apache.atlas.typesystem.persistence.Id.EntityState;
import org.apache.atlas.typesystem.types.TypeSystem;
import org.testng.Assert;
import java.util.List;
import java.util.Map;
import static org.apache.atlas.TestUtils.COLUMNS_ATTR_NAME;
import static org.apache.atlas.TestUtils.NAME;
import static org.apache.atlas.TestUtils.PII;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
public class GraphBackedRepositorySoftDeleteTest extends GraphBackedMetadataRepositoryDeleteTestBase {
@Override
DeleteHandler getDeleteHandler(TypeSystem typeSystem) {
return new SoftDeleteHandler(typeSystem);
}
@Override
protected void assertTestDeleteEntityWithTraits(String guid) throws Exception {
ITypedReferenceableInstance instance = repositoryService.getEntityDefinition(guid);
assertTrue(instance.getTraits().contains(PII));
}
@Override
protected void assertTableForTestDeleteReference(String tableId) throws Exception {
ITypedReferenceableInstance table = repositoryService.getEntityDefinition(tableId);
assertNotNull(table.get(NAME));
assertNotNull(table.get("description"));
assertNotNull(table.get("type"));
assertNotNull(table.get("tableType"));
assertNotNull(table.get("created"));
Id dbId = (Id) table.get("database");
assertNotNull(dbId);
ITypedReferenceableInstance db = repositoryService.getEntityDefinition(dbId.getId()._getId());
assertNotNull(db);
assertEquals(db.getId().getState(), Id.EntityState.ACTIVE);
}
@Override
protected void assertColumnForTestDeleteReference(ITypedReferenceableInstance tableInstance) throws AtlasException {
List<ITypedReferenceableInstance> columns =
(List<ITypedReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME);
assertEquals(columns.size(), 1);
assertEquals(columns.get(0).getId().getState(), Id.EntityState.DELETED);
}
@Override
protected void assertProcessForTestDeleteReference(ITypedReferenceableInstance expected) throws Exception {
ITypedReferenceableInstance process = repositoryService.getEntityDefinition(expected.getId()._getId());
List<ITypedReferenceableInstance> outputs =
(List<ITypedReferenceableInstance>) process.get(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS);
List<ITypedReferenceableInstance> expectedOutputs =
(List<ITypedReferenceableInstance>) process.get(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS);
assertEquals(outputs.size(), expectedOutputs.size());
}
@Override
protected void assertEntityDeleted(String id) throws Exception {
ITypedReferenceableInstance entity = repositoryService.getEntityDefinition(id);
assertEquals(entity.getId().getState(), Id.EntityState.DELETED);
}
@Override
protected void assertDeletedColumn(ITypedReferenceableInstance tableInstance) throws AtlasException {
List<IReferenceableInstance> columns = (List<IReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME);
assertEquals(columns.size(), 3);
assertEquals(columns.get(0).getId().getState(), Id.EntityState.DELETED);
}
@Override
protected void assertTestDeleteEntities(ITypedReferenceableInstance expected) throws Exception {
//Assert that the deleted table can be fully constructed back
ITypedReferenceableInstance table = repositoryService.getEntityDefinition(expected.getId()._getId());
List<ITypedReferenceableInstance> columns =
(List<ITypedReferenceableInstance>) table.get(TestUtils.COLUMNS_ATTR_NAME);
List<ITypedReferenceableInstance> expectedColumns =
(List<ITypedReferenceableInstance>) table.get(TestUtils.COLUMNS_ATTR_NAME);
assertEquals(columns.size(), expectedColumns.size());
assertNotNull(table.get("database"));
}
@Override
protected void assertVerticesDeleted(List<AtlasVertex> vertices) {
for (AtlasVertex vertex : vertices) {
assertEquals(GraphHelper.getSingleValuedProperty(vertex, Constants.STATE_PROPERTY_KEY, String.class), Id.EntityState.DELETED.name());
}
}
@Override
protected void assertTestUpdateEntity_MultiplicityOneNonCompositeReference(String janeGuid) throws Exception {
// Verify Jane's subordinates reference cardinality is still 2.
ITypedReferenceableInstance jane = repositoryService.getEntityDefinition(janeGuid);
List<ITypedReferenceableInstance> subordinates = (List<ITypedReferenceableInstance>) jane.get("subordinates");
Assert.assertEquals(subordinates.size(), 2);
}
@Override
protected void assertJohnForTestDisconnectBidirectionalReferences(ITypedReferenceableInstance john, String janeGuid)
throws Exception {
Id mgr = (Id) john.get("manager");
assertNotNull(mgr);
assertEquals(mgr._getId(), janeGuid);
assertEquals(mgr.getState(), Id.EntityState.DELETED);
}
@Override
protected void assertMaxForTestDisconnectBidirectionalReferences(Map<String, String> nameGuidMap) throws Exception {
// Verify that the Department.employees reference to the deleted employee
// was disconnected.
ITypedReferenceableInstance hrDept = repositoryService.getEntityDefinition(nameGuidMap.get("hr"));
List<ITypedReferenceableInstance> employees = (List<ITypedReferenceableInstance>) hrDept.get("employees");
Assert.assertEquals(employees.size(), 4);
String maxGuid = nameGuidMap.get("Max");
for (ITypedReferenceableInstance employee : employees) {
if (employee.getId()._getId().equals(maxGuid)) {
assertEquals(employee.getId().getState(), Id.EntityState.DELETED);
}
}
// Verify that the Manager.subordinates still references deleted employee
ITypedReferenceableInstance jane = repositoryService.getEntityDefinition(nameGuidMap.get("Jane"));
List<ITypedReferenceableInstance> subordinates = (List<ITypedReferenceableInstance>) jane.get("subordinates");
assertEquals(subordinates.size(), 2);
for (ITypedReferenceableInstance subordinate : subordinates) {
if (subordinate.getId()._getId().equals(maxGuid)) {
assertEquals(subordinate.getId().getState(), Id.EntityState.DELETED);
}
}
// Verify that max's Person.mentor unidirectional reference to john was disconnected.
ITypedReferenceableInstance john = repositoryService.getEntityDefinition(nameGuidMap.get("John"));
Id mentor = (Id) john.get("mentor");
assertEquals(mentor._getId(), maxGuid);
assertEquals(mentor.getState(), Id.EntityState.DELETED);
}
@Override
protected void assertTestDisconnectUnidirectionalArrayReferenceFromClassType(
List<ITypedReferenceableInstance> columns, String columnGuid) {
Assert.assertEquals(columns.size(), 5);
for (ITypedReferenceableInstance column : columns) {
if (column.getId()._getId().equals(columnGuid)) {
assertEquals(column.getId().getState(), Id.EntityState.DELETED);
} else {
assertEquals(column.getId().getState(), Id.EntityState.ACTIVE);
}
}
}
@Override
protected void assertTestDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes(String structContainerGuid)
throws Exception {
// Verify that the unidirectional references from the struct and trait instances
// to the deleted entities were not disconnected.
ITypedReferenceableInstance structContainerConvertedEntity =
repositoryService.getEntityDefinition(structContainerGuid);
ITypedStruct struct = (ITypedStruct) structContainerConvertedEntity.get("struct");
assertNotNull(struct.get("target"));
IStruct trait = structContainerConvertedEntity.getTrait("TestTrait");
assertNotNull(trait);
assertNotNull(trait.get("target"));
}
@Override
protected void assertTestDisconnectMapReferenceFromClassType(String mapOwnerGuid) throws Exception {
ITypedReferenceableInstance mapOwnerInstance = repositoryService.getEntityDefinition(mapOwnerGuid);
Map<String, ITypedReferenceableInstance> map =
(Map<String, ITypedReferenceableInstance>) mapOwnerInstance.get("map");
assertNotNull(map);
assertEquals(map.size(), 1);
Map<String, ITypedReferenceableInstance> biMap =
(Map<String, ITypedReferenceableInstance>) mapOwnerInstance.get("biMap");
assertNotNull(biMap);
assertEquals(biMap.size(), 1);
}
@Override
protected void assertTestDeleteTargetOfMultiplicityRequiredReference() throws Exception {
// No-op - it's ok that no exception was thrown if soft deletes are enabled.
}
@Override
protected void assertTestLowerBoundsIgnoredOnDeletedEntities(List<ITypedReferenceableInstance> employees) {
Assert.assertEquals(employees.size(), 4, "References to deleted employees should not have been disconnected with soft deletes enabled");
}
@Override
protected void assertTestLowerBoundsIgnoredOnCompositeDeletedEntities(String hrDeptGuid) throws Exception {
ITypedReferenceableInstance hrDept = repositoryService.getEntityDefinition(hrDeptGuid);
Assert.assertEquals(hrDept.getId().getState(), EntityState.DELETED);
}
@Override
protected void verifyTestDeleteEntityWithDuplicateReferenceListElements(List columnsPropertyValue) {
// With soft deletes enabled, verify that edge IDs for deleted edges
// were not removed from the array property list.
Assert.assertEquals(columnsPropertyValue.size(), 4);
}
}