| /** |
| * 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.type; |
| |
| |
| import org.apache.atlas.exception.AtlasBaseException; |
| import org.apache.atlas.model.typedef.*; |
| import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef; |
| import org.apache.atlas.type.AtlasTypeRegistry.AtlasTransientTypeRegistry; |
| import org.testng.annotations.Test; |
| |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.Callable; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.Executors; |
| import java.util.concurrent.TimeUnit; |
| |
| import static org.testng.Assert.*; |
| |
| public class TestAtlasTypeRegistry { |
| |
| /* |
| * L0 |
| * / \ |
| * / \ |
| * L1_1---- L1_2 |
| * / \ \ / \ |
| * / \ \ / \ |
| * L2_1 L2_2 L2_3 L2_4 |
| */ |
| @Test |
| public void testClassificationDefValidHierarchy() { |
| AtlasClassificationDef classifiL0 = new AtlasClassificationDef("L0"); |
| AtlasClassificationDef classifiL1_1 = new AtlasClassificationDef("L1-1"); |
| AtlasClassificationDef classifiL1_2 = new AtlasClassificationDef("L1-2"); |
| AtlasClassificationDef classifiL2_1 = new AtlasClassificationDef("L2-1"); |
| AtlasClassificationDef classifiL2_2 = new AtlasClassificationDef("L2-2"); |
| AtlasClassificationDef classifiL2_3 = new AtlasClassificationDef("L2-3"); |
| AtlasClassificationDef classifiL2_4 = new AtlasClassificationDef("L2-4"); |
| |
| classifiL1_1.addSuperType(classifiL0.getName()); |
| classifiL1_2.addSuperType(classifiL0.getName()); |
| classifiL2_1.addSuperType(classifiL1_1.getName()); |
| classifiL2_2.addSuperType(classifiL1_1.getName()); |
| classifiL2_3.addSuperType(classifiL1_1.getName()); |
| classifiL2_3.addSuperType(classifiL1_2.getName()); |
| classifiL2_4.addSuperType(classifiL1_2.getName()); |
| |
| classifiL0.addAttribute(new AtlasAttributeDef("L0_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| classifiL1_1.addAttribute(new AtlasAttributeDef("L1-1_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| classifiL1_2.addAttribute(new AtlasAttributeDef("L1-2_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| classifiL2_1.addAttribute(new AtlasAttributeDef("L2-1_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| classifiL2_2.addAttribute(new AtlasAttributeDef("L2-2_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| classifiL2_3.addAttribute(new AtlasAttributeDef("L2-3_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| classifiL2_4.addAttribute(new AtlasAttributeDef("L2-4_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| |
| AtlasTypesDef typesDef = new AtlasTypesDef(); |
| |
| typesDef.getClassificationDefs().add(classifiL0); |
| typesDef.getClassificationDefs().add(classifiL1_1); |
| typesDef.getClassificationDefs().add(classifiL1_2); |
| typesDef.getClassificationDefs().add(classifiL2_1); |
| typesDef.getClassificationDefs().add(classifiL2_2); |
| typesDef.getClassificationDefs().add(classifiL2_3); |
| typesDef.getClassificationDefs().add(classifiL2_4); |
| |
| AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); |
| AtlasTransientTypeRegistry ttr = null; |
| boolean commit = false; |
| String failureMsg = null; |
| |
| try { |
| ttr = typeRegistry.lockTypeRegistryForUpdate(); |
| |
| ttr.addTypes(typesDef); |
| |
| commit = true; |
| } catch (AtlasBaseException excp) { |
| failureMsg = excp.getMessage(); |
| } finally { |
| typeRegistry.releaseTypeRegistryForUpdate(ttr, commit); |
| } |
| assertNull(failureMsg); |
| |
| |
| validateSuperTypes(typeRegistry, "L0", new HashSet<String>()); |
| validateSuperTypes(typeRegistry, "L1-1", new HashSet<>(Arrays.asList("L0"))); |
| validateSuperTypes(typeRegistry, "L1-2", new HashSet<>(Arrays.asList("L0"))); |
| validateSuperTypes(typeRegistry, "L2-1", new HashSet<>(Arrays.asList("L1-1", "L0"))); |
| validateSuperTypes(typeRegistry, "L2-2", new HashSet<>(Arrays.asList("L1-1", "L0"))); |
| validateSuperTypes(typeRegistry, "L2-3", new HashSet<>(Arrays.asList("L1-1", "L0", "L1-2"))); |
| validateSuperTypes(typeRegistry, "L2-4", new HashSet<>(Arrays.asList("L1-2", "L0"))); |
| |
| validateSubTypes(typeRegistry, "L0", new HashSet<>(Arrays.asList("L1-1", "L1-2", "L2-1", "L2-2", "L2-3", "L2-4"))); |
| validateSubTypes(typeRegistry, "L1-1", new HashSet<>(Arrays.asList("L2-1", "L2-2", "L2-3"))); |
| validateSubTypes(typeRegistry, "L1-2", new HashSet<>(Arrays.asList("L2-3", "L2-4"))); |
| validateSubTypes(typeRegistry, "L2-1", new HashSet<String>()); |
| validateSubTypes(typeRegistry, "L2-2", new HashSet<String>()); |
| validateSubTypes(typeRegistry, "L2-3", new HashSet<String>()); |
| validateSubTypes(typeRegistry, "L2-4", new HashSet<String>()); |
| |
| validateAttributeNames(typeRegistry, "L0", new HashSet<>(Arrays.asList("L0_a1"))); |
| validateAttributeNames(typeRegistry, "L1-1", new HashSet<>(Arrays.asList("L0_a1", "L1-1_a1"))); |
| validateAttributeNames(typeRegistry, "L1-2", new HashSet<>(Arrays.asList("L0_a1", "L1-2_a1"))); |
| validateAttributeNames(typeRegistry, "L2-1", new HashSet<>(Arrays.asList("L0_a1", "L1-1_a1", "L2-1_a1"))); |
| validateAttributeNames(typeRegistry, "L2-2", new HashSet<>(Arrays.asList("L0_a1", "L1-1_a1", "L2-2_a1"))); |
| validateAttributeNames(typeRegistry, "L2-3", new HashSet<>(Arrays.asList("L0_a1", "L1-1_a1", "L1-2_a1", "L2-3_a1"))); |
| validateAttributeNames(typeRegistry, "L2-4", new HashSet<>(Arrays.asList("L0_a1", "L1-2_a1", "L2-4_a1"))); |
| } |
| |
| @Test |
| public void testClassificationDefInvalidHierarchy_Self() { |
| AtlasClassificationDef classifiDef1 = new AtlasClassificationDef("classifiDef-1"); |
| |
| classifiDef1.addSuperType(classifiDef1.getName()); |
| |
| AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); |
| AtlasTransientTypeRegistry ttr = null; |
| boolean commit = false; |
| String failureMsg = null; |
| |
| try { |
| ttr = typeRegistry.lockTypeRegistryForUpdate(); |
| |
| ttr.addType(classifiDef1); |
| |
| commit = true; |
| } catch (AtlasBaseException excp) { |
| failureMsg = excp.getMessage(); |
| } finally { |
| typeRegistry.releaseTypeRegistryForUpdate(ttr, commit); |
| } |
| assertNotNull(failureMsg, "expected invalid supertype failure"); |
| } |
| |
| /* |
| * L2_3 |
| * \ |
| * L0 |
| * / \ |
| * / \ |
| * L1_1---- L1_2 |
| * / \ \ / \ |
| * / \ \ / \ |
| * L2_1 L2_2 L2_3 L2_4 |
| */ |
| @Test |
| public void testClassificationDefInvalidHierarchy_CircularRef() { |
| AtlasClassificationDef classifiL0 = new AtlasClassificationDef("L0"); |
| AtlasClassificationDef classifiL1_1 = new AtlasClassificationDef("L1-1"); |
| AtlasClassificationDef classifiL1_2 = new AtlasClassificationDef("L1-2"); |
| AtlasClassificationDef classifiL2_1 = new AtlasClassificationDef("L2-1"); |
| AtlasClassificationDef classifiL2_2 = new AtlasClassificationDef("L2-2"); |
| AtlasClassificationDef classifiL2_3 = new AtlasClassificationDef("L2-3"); |
| AtlasClassificationDef classifiL2_4 = new AtlasClassificationDef("L2-4"); |
| |
| classifiL1_1.addSuperType(classifiL0.getName()); |
| classifiL1_2.addSuperType(classifiL0.getName()); |
| classifiL2_1.addSuperType(classifiL1_1.getName()); |
| classifiL2_2.addSuperType(classifiL1_1.getName()); |
| classifiL2_3.addSuperType(classifiL1_1.getName()); |
| classifiL2_3.addSuperType(classifiL1_2.getName()); |
| classifiL2_4.addSuperType(classifiL1_2.getName()); |
| classifiL0.addSuperType(classifiL2_3.getName()); // circular-ref |
| |
| AtlasTypesDef typesDef = new AtlasTypesDef(); |
| |
| typesDef.getClassificationDefs().add(classifiL0); |
| typesDef.getClassificationDefs().add(classifiL1_1); |
| typesDef.getClassificationDefs().add(classifiL1_2); |
| typesDef.getClassificationDefs().add(classifiL2_1); |
| typesDef.getClassificationDefs().add(classifiL2_2); |
| typesDef.getClassificationDefs().add(classifiL2_3); |
| typesDef.getClassificationDefs().add(classifiL2_4); |
| |
| AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); |
| AtlasTransientTypeRegistry ttr = null; |
| boolean commit = false; |
| String failureMsg = null; |
| |
| try { |
| ttr = typeRegistry.lockTypeRegistryForUpdate(); |
| |
| ttr.addTypes(typesDef); |
| |
| commit = true; |
| } catch (AtlasBaseException excp) { |
| failureMsg = excp.getMessage(); |
| } finally { |
| typeRegistry.releaseTypeRegistryForUpdate(ttr, commit); |
| } |
| assertNotNull(failureMsg, "expected invalid supertype failure"); |
| } |
| |
| /* |
| * L0 |
| * / \ |
| * / \ |
| * L1_1---- L1_2 |
| * / \ \ / \ |
| * / \ \ / \ |
| * L2_1 L2_2 L2_3 L2_4 |
| */ |
| @Test |
| public void testEntityDefValidHierarchy() { |
| AtlasEntityDef entL0 = new AtlasEntityDef("L0"); |
| AtlasEntityDef entL1_1 = new AtlasEntityDef("L1-1"); |
| AtlasEntityDef entL1_2 = new AtlasEntityDef("L1-2"); |
| AtlasEntityDef entL2_1 = new AtlasEntityDef("L2-1"); |
| AtlasEntityDef entL2_2 = new AtlasEntityDef("L2-2"); |
| AtlasEntityDef entL2_3 = new AtlasEntityDef("L2-3"); |
| AtlasEntityDef entL2_4 = new AtlasEntityDef("L2-4"); |
| |
| entL1_1.addSuperType(entL0.getName()); |
| entL1_2.addSuperType(entL0.getName()); |
| entL2_1.addSuperType(entL1_1.getName()); |
| entL2_2.addSuperType(entL1_1.getName()); |
| entL2_3.addSuperType(entL1_1.getName()); |
| entL2_3.addSuperType(entL1_2.getName()); |
| entL2_4.addSuperType(entL1_2.getName()); |
| |
| entL0.addAttribute(new AtlasAttributeDef("L0_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| entL1_1.addAttribute(new AtlasAttributeDef("L1-1_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| entL1_2.addAttribute(new AtlasAttributeDef("L1-2_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| entL2_1.addAttribute(new AtlasAttributeDef("L2-1_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| entL2_2.addAttribute(new AtlasAttributeDef("L2-2_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| entL2_3.addAttribute(new AtlasAttributeDef("L2-3_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| entL2_4.addAttribute(new AtlasAttributeDef("L2-4_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| |
| AtlasTypesDef typesDef = new AtlasTypesDef(); |
| |
| typesDef.getEntityDefs().add(entL0); |
| typesDef.getEntityDefs().add(entL1_1); |
| typesDef.getEntityDefs().add(entL1_2); |
| typesDef.getEntityDefs().add(entL2_1); |
| typesDef.getEntityDefs().add(entL2_2); |
| typesDef.getEntityDefs().add(entL2_3); |
| typesDef.getEntityDefs().add(entL2_4); |
| |
| AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); |
| AtlasTransientTypeRegistry ttr = null; |
| boolean commit = false; |
| String failureMsg = null; |
| |
| try { |
| ttr = typeRegistry.lockTypeRegistryForUpdate(); |
| |
| ttr.addTypes(typesDef); |
| |
| commit = true; |
| } catch (AtlasBaseException excp) { |
| failureMsg = excp.getMessage(); |
| } finally { |
| typeRegistry.releaseTypeRegistryForUpdate(ttr, commit); |
| } |
| assertNull(failureMsg); |
| |
| validateSuperTypes(typeRegistry, "L0", new HashSet<String>()); |
| validateSuperTypes(typeRegistry, "L1-1", new HashSet<>(Arrays.asList("L0"))); |
| validateSuperTypes(typeRegistry, "L1-2", new HashSet<>(Arrays.asList("L0"))); |
| validateSuperTypes(typeRegistry, "L2-1", new HashSet<>(Arrays.asList("L1-1", "L0"))); |
| validateSuperTypes(typeRegistry, "L2-2", new HashSet<>(Arrays.asList("L1-1", "L0"))); |
| validateSuperTypes(typeRegistry, "L2-3", new HashSet<>(Arrays.asList("L1-1", "L0", "L1-2"))); |
| validateSuperTypes(typeRegistry, "L2-4", new HashSet<>(Arrays.asList("L1-2", "L0"))); |
| |
| validateSubTypes(typeRegistry, "L0", new HashSet<>(Arrays.asList("L1-1", "L1-2", "L2-1", "L2-2", "L2-3", "L2-4"))); |
| validateSubTypes(typeRegistry, "L1-1", new HashSet<>(Arrays.asList("L2-1", "L2-2", "L2-3"))); |
| validateSubTypes(typeRegistry, "L1-2", new HashSet<>(Arrays.asList("L2-3", "L2-4"))); |
| validateSubTypes(typeRegistry, "L2-1", new HashSet<String>()); |
| validateSubTypes(typeRegistry, "L2-2", new HashSet<String>()); |
| validateSubTypes(typeRegistry, "L2-3", new HashSet<String>()); |
| validateSubTypes(typeRegistry, "L2-4", new HashSet<String>()); |
| |
| validateAttributeNames(typeRegistry, "L0", new HashSet<>(Arrays.asList("L0_a1"))); |
| validateAttributeNames(typeRegistry, "L1-1", new HashSet<>(Arrays.asList("L0_a1", "L1-1_a1"))); |
| validateAttributeNames(typeRegistry, "L1-2", new HashSet<>(Arrays.asList("L0_a1", "L1-2_a1"))); |
| validateAttributeNames(typeRegistry, "L2-1", new HashSet<>(Arrays.asList("L0_a1", "L1-1_a1", "L2-1_a1"))); |
| validateAttributeNames(typeRegistry, "L2-2", new HashSet<>(Arrays.asList("L0_a1", "L1-1_a1", "L2-2_a1"))); |
| validateAttributeNames(typeRegistry, "L2-3", new HashSet<>(Arrays.asList("L0_a1", "L1-1_a1", "L1-2_a1", "L2-3_a1"))); |
| validateAttributeNames(typeRegistry, "L2-4", new HashSet<>(Arrays.asList("L0_a1", "L1-2_a1", "L2-4_a1"))); |
| } |
| |
| @Test |
| public void testEntityDefInvalidHierarchy_Self() { |
| AtlasEntityDef entDef1 = new AtlasEntityDef("entDef-1"); |
| |
| entDef1.addSuperType(entDef1.getName()); |
| |
| AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); |
| AtlasTransientTypeRegistry ttr = null; |
| boolean commit = false; |
| String failureMsg = null; |
| |
| try { |
| ttr = typeRegistry.lockTypeRegistryForUpdate(); |
| |
| ttr.addType(entDef1); |
| |
| commit = true; |
| } catch (AtlasBaseException excp) { |
| failureMsg = excp.getMessage(); |
| } finally { |
| typeRegistry.releaseTypeRegistryForUpdate(ttr, commit); |
| } |
| assertNotNull(failureMsg, "expected invalid supertype failure"); |
| } |
| |
| /* |
| * L2_3 |
| * \ |
| * L0 |
| * / \ |
| * / \ |
| * L1_1---- L1_2 |
| * / \ \ / \ |
| * / \ \ / \ |
| * L2_1 L2_2 L2_3 L2_4 |
| */ |
| @Test |
| public void testEntityDefInvalidHierarchy_CircularRef() { |
| AtlasEntityDef entL0 = new AtlasEntityDef("L0"); |
| AtlasEntityDef entL1_1 = new AtlasEntityDef("L1-1"); |
| AtlasEntityDef entL1_2 = new AtlasEntityDef("L1-2"); |
| AtlasEntityDef entL2_1 = new AtlasEntityDef("L2-1"); |
| AtlasEntityDef entL2_2 = new AtlasEntityDef("L2-2"); |
| AtlasEntityDef entL2_3 = new AtlasEntityDef("L2-3"); |
| AtlasEntityDef entL2_4 = new AtlasEntityDef("L2-4"); |
| |
| entL1_1.addSuperType(entL0.getName()); |
| entL1_2.addSuperType(entL0.getName()); |
| entL2_1.addSuperType(entL1_1.getName()); |
| entL2_2.addSuperType(entL1_1.getName()); |
| entL2_3.addSuperType(entL1_1.getName()); |
| entL2_3.addSuperType(entL1_2.getName()); |
| entL2_4.addSuperType(entL1_2.getName()); |
| entL0.addSuperType(entL2_3.getName()); // circular-ref |
| |
| AtlasTypesDef typesDef = new AtlasTypesDef(); |
| |
| typesDef.getEntityDefs().add(entL0); |
| typesDef.getEntityDefs().add(entL1_1); |
| typesDef.getEntityDefs().add(entL1_2); |
| typesDef.getEntityDefs().add(entL2_1); |
| typesDef.getEntityDefs().add(entL2_2); |
| typesDef.getEntityDefs().add(entL2_3); |
| typesDef.getEntityDefs().add(entL2_4); |
| |
| AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); |
| AtlasTransientTypeRegistry ttr = null; |
| boolean commit = false; |
| String failureMsg = null; |
| |
| try { |
| ttr = typeRegistry.lockTypeRegistryForUpdate(); |
| |
| ttr.addTypes(typesDef); |
| |
| commit = true; |
| } catch (AtlasBaseException excp) { |
| failureMsg = excp.getMessage(); |
| } finally { |
| typeRegistry.releaseTypeRegistryForUpdate(ttr, commit); |
| } |
| assertNotNull(failureMsg, "expected invalid supertype failure"); |
| } |
| |
| @Test |
| public void testNestedUpdates() { |
| AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); |
| AtlasTransientTypeRegistry ttr = null; |
| boolean commit = false; |
| String failureMsg = null; |
| AtlasClassificationDef testTag1 = new AtlasClassificationDef("testTag1"); |
| AtlasClassificationDef testTag2 = new AtlasClassificationDef("testTag2"); |
| |
| try { |
| ttr = typeRegistry.lockTypeRegistryForUpdate(); |
| |
| ttr.addType(testTag1); |
| |
| // changes should not be seen in typeRegistry until lock is released |
| assertFalse(typeRegistry.isRegisteredType(testTag1.getName()), |
| "type added should be seen in typeRegistry only after commit"); |
| |
| boolean isNestedUpdateSuccess = addType(typeRegistry, testTag2); |
| |
| assertTrue(isNestedUpdateSuccess); |
| |
| // changes made in nested commit, inside addType(), should not be seen in typeRegistry until lock is released here |
| assertFalse(typeRegistry.isRegisteredType(testTag2.getName()), |
| "type added within nested commit should be seen in typeRegistry only after outer commit"); |
| |
| commit = true; |
| } catch (AtlasBaseException excp) { |
| failureMsg = excp.getMessage(); |
| } finally { |
| typeRegistry.releaseTypeRegistryForUpdate(ttr, commit); |
| } |
| assertNull(failureMsg); |
| assertTrue(typeRegistry.isRegisteredType(testTag1.getName())); |
| assertTrue(typeRegistry.isRegisteredType(testTag2.getName())); |
| } |
| |
| @Test |
| public void testParallelUpdates() { |
| final int numOfThreads = 3; |
| final int numOfTypesPerKind = 30; |
| final String enumTypePrefix = "testEnum-"; |
| final String structTypePrefix = "testStruct-"; |
| final String classificationPrefix = "testTag-"; |
| final String entityTypePrefix = "testEntity-"; |
| |
| ExecutorService executor = Executors.newFixedThreadPool(numOfThreads); |
| |
| final AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); |
| |
| // update typeRegistry simultaneously in multiple threads |
| for (int threadIdx = 0; threadIdx < numOfThreads; threadIdx++) { |
| executor.submit(new Callable<Object>() { |
| @Override |
| public Object call() throws Exception { |
| for (int i = 0; i < numOfTypesPerKind; i++) { |
| addType(typeRegistry, new AtlasEnumDef(enumTypePrefix + i)); |
| } |
| |
| for (int i = 0; i < numOfTypesPerKind; i++) { |
| addType(typeRegistry, new AtlasStructDef(structTypePrefix + i)); |
| } |
| |
| for (int i = 0; i < numOfTypesPerKind; i++) { |
| addType(typeRegistry, new AtlasClassificationDef(classificationPrefix + i)); |
| } |
| |
| for (int i = 0; i < numOfTypesPerKind; i++) { |
| addType(typeRegistry, new AtlasEntityDef(entityTypePrefix + i)); |
| } |
| |
| return null; |
| } |
| }); |
| } |
| |
| executor.shutdown(); |
| |
| try { |
| boolean isCompleted = executor.awaitTermination(60, TimeUnit.SECONDS); |
| |
| assertTrue(isCompleted, "threads did not complete updating types"); |
| } catch (InterruptedException excp) { |
| // ignore? |
| } |
| |
| // verify that all types added are present in the typeRegistry |
| for (int i = 0; i < numOfTypesPerKind; i++) { |
| String enumType = enumTypePrefix + i; |
| String structType = structTypePrefix + i; |
| String classificationType = classificationPrefix + i; |
| String entityType = entityTypePrefix + i; |
| |
| assertNotNull(typeRegistry.getEnumDefByName(enumType), enumType + ": enum not found"); |
| assertNotNull(typeRegistry.getStructDefByName(structType), structType + ": struct not found"); |
| assertNotNull(typeRegistry.getClassificationDefByName(classificationType), classificationType + ": classification not found"); |
| assertNotNull(typeRegistry.getEntityDefByName(entityType), entityType + ": entity not found"); |
| } |
| } |
| |
| /* create 2 entity types: L0 and L1, with L0 as superType of L1 |
| * add entity type L2, with L0, L1 and L2 as super-types - this should fail due to L2 self-referencing itself in super-types |
| * verify that after the update failure, the registry still has correct super-type/sub-type information for L0 and L1 |
| */ |
| @Test |
| public void testRegistryValidityOnInvalidUpdate() { |
| AtlasEntityDef entL0 = new AtlasEntityDef("L0"); |
| AtlasEntityDef entL1 = new AtlasEntityDef("L1"); |
| |
| entL1.addSuperType(entL0.getName()); |
| |
| entL0.addAttribute(new AtlasAttributeDef("L0_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| entL1.addAttribute(new AtlasAttributeDef("L1_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); |
| |
| AtlasTypesDef typesDef = new AtlasTypesDef(); |
| |
| typesDef.getEntityDefs().add(entL0); |
| typesDef.getEntityDefs().add(entL1); |
| |
| AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); |
| AtlasTransientTypeRegistry ttr = null; |
| boolean commit = false; |
| String failureMsg = null; |
| |
| try { |
| ttr = typeRegistry.lockTypeRegistryForUpdate(); |
| |
| ttr.addTypes(typesDef); |
| |
| commit = true; |
| } catch (AtlasBaseException excp) { |
| failureMsg = excp.getMessage(); |
| } finally { |
| typeRegistry.releaseTypeRegistryForUpdate(ttr, commit); |
| } |
| assertNull(failureMsg); |
| |
| validateSuperTypes(typeRegistry, "L0", new HashSet<String>()); |
| validateSubTypes(typeRegistry, "L0", new HashSet<>(Arrays.asList("L1"))); |
| |
| validateSuperTypes(typeRegistry, "L1", new HashSet<>(Arrays.asList("L0"))); |
| validateSubTypes(typeRegistry, "L1", new HashSet<String>()); |
| |
| |
| // create a circular reference |
| AtlasEntityDef entL2 = new AtlasEntityDef("L2"); |
| entL2.addSuperType(entL0.getName()); |
| entL2.addSuperType(entL1.getName()); |
| entL2.addSuperType(entL2.getName()); |
| |
| typesDef.clear(); |
| typesDef.getEntityDefs().add(entL2); |
| |
| try { |
| commit = false; |
| |
| ttr = typeRegistry.lockTypeRegistryForUpdate(); |
| |
| ttr.updateTypes(typesDef); |
| |
| commit = true; |
| } catch (AtlasBaseException excp) { |
| failureMsg = excp.getMessage(); |
| } finally { |
| typeRegistry.releaseTypeRegistryForUpdate(ttr, commit); |
| } |
| assertNotNull(failureMsg); |
| |
| assertNull(typeRegistry.getEntityTypeByName("L2")); |
| |
| validateSuperTypes(typeRegistry, "L0", new HashSet<String>()); |
| validateSubTypes(typeRegistry, "L0", new HashSet<>(Arrays.asList("L1"))); |
| |
| validateSuperTypes(typeRegistry, "L1", new HashSet<>(Arrays.asList("L0"))); |
| validateSubTypes(typeRegistry, "L1", new HashSet<String>()); |
| } |
| |
| private boolean addType(AtlasTypeRegistry typeRegistry, AtlasBaseTypeDef typeDef) { |
| boolean ret = false; |
| AtlasTransientTypeRegistry ttr = null; |
| |
| try { |
| ttr = typeRegistry.lockTypeRegistryForUpdate(); |
| |
| ttr.addType(typeDef); |
| |
| ret = true; |
| } catch (AtlasBaseException excp) { |
| // ignore |
| } finally { |
| typeRegistry.releaseTypeRegistryForUpdate(ttr, ret); |
| } |
| |
| return ret; |
| } |
| |
| private void validateSuperTypes(AtlasTypeRegistry typeRegistry, String typeName, Set<String> expectedSuperTypes) { |
| AtlasType type = null; |
| |
| try { |
| type = typeRegistry.getType(typeName); |
| } catch (AtlasBaseException excp) { |
| } |
| |
| Set<String> superTypes = null; |
| |
| if (type != null) { |
| if (type instanceof AtlasEntityType) { |
| superTypes = ((AtlasEntityType) type).getAllSuperTypes(); |
| } else if (type instanceof AtlasClassificationType) { |
| superTypes = ((AtlasClassificationType) type).getAllSuperTypes(); |
| } |
| } |
| |
| assertEquals(superTypes, expectedSuperTypes); |
| } |
| |
| private void validateSubTypes(AtlasTypeRegistry typeRegistry, String typeName, Set<String> expectedSubTypes) { |
| AtlasType type = null; |
| |
| try { |
| type = typeRegistry.getType(typeName); |
| } catch (AtlasBaseException excp) { |
| } |
| |
| Set<String> subTypes = null; |
| |
| if (type != null) { |
| if (type instanceof AtlasEntityType) { |
| subTypes = ((AtlasEntityType) type).getAllSubTypes(); |
| } else if (type instanceof AtlasClassificationType) { |
| subTypes = ((AtlasClassificationType) type).getAllSubTypes(); |
| } |
| } |
| |
| assertEquals(subTypes, expectedSubTypes); |
| } |
| |
| private void validateAttributeNames(AtlasTypeRegistry typeRegistry, String typeName, Set<String> attributeNames) { |
| AtlasType type = null; |
| |
| try { |
| type = typeRegistry.getType(typeName); |
| } catch (AtlasBaseException excp) { |
| } |
| |
| Map<String, AtlasStructType.AtlasAttribute> attributes = null; |
| |
| if (type != null) { |
| if (type instanceof AtlasEntityType) { |
| attributes = ((AtlasEntityType) type).getAllAttributes(); |
| } else if (type instanceof AtlasClassificationType) { |
| attributes = ((AtlasClassificationType) type).getAllAttributes(); |
| } |
| } |
| |
| assertNotNull(attributes); |
| assertEquals(attributes.keySet(), attributeNames); |
| } |
| } |