blob: 3c53c02b48747515217c9327c98209a48ee84237 [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
*
* 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 java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.ModelTestUtil;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
import org.apache.atlas.type.AtlasTypeRegistry.AtlasTransientTypeRegistry;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class TestAtlasEntityType {
private static final String TYPE_TABLE = "my_table";
private static final String TYPE_COLUMN = "my_column";
private static final String ATTR_TABLE = "table";
private static final String ATTR_COLUMNS = "columns";
private static final String ATTR_NAME = "name";
private final AtlasEntityType entityType;
private final List<Object> validValues = new ArrayList<>();
private final List<Object> invalidValues = new ArrayList<>();
{
entityType = getEntityType(ModelTestUtil.getEntityDefWithSuperTypes());
AtlasEntity invalidValue1 = entityType.createDefaultValue();
AtlasEntity invalidValue2 = entityType.createDefaultValue();
Map<String, Object> invalidValue3 = entityType.createDefaultValue().getAttributes();
// invalid value for int
invalidValue1.setAttribute(ModelTestUtil.getDefaultAttributeName(AtlasBaseTypeDef.ATLAS_TYPE_INT), "xyz");
// invalid value for date
invalidValue2.setAttribute(ModelTestUtil.getDefaultAttributeName(AtlasBaseTypeDef.ATLAS_TYPE_DATE), "xyz");
// invalid value for bigint
invalidValue3.put(ModelTestUtil.getDefaultAttributeName(AtlasBaseTypeDef.ATLAS_TYPE_BIGINTEGER), "xyz");
validValues.add(null);
validValues.add(entityType.createDefaultValue());
validValues.add(entityType.createDefaultValue().getAttributes()); // Map<String, Object>
invalidValues.add(invalidValue1);
invalidValues.add(invalidValue2);
invalidValues.add(invalidValue3);
invalidValues.add(new AtlasEntity()); // no values for mandatory attributes
invalidValues.add(new HashMap<>()); // no values for mandatory attributes
invalidValues.add(1); // incorrect datatype
invalidValues.add(new HashSet()); // incorrect datatype
invalidValues.add(new ArrayList()); // incorrect datatype
invalidValues.add(new String[] {}); // incorrect datatype
}
@Test
public void testEntityTypeDefaultValue() {
AtlasEntity defValue = entityType.createDefaultValue();
assertNotNull(defValue);
assertEquals(defValue.getTypeName(), entityType.getTypeName());
}
@Test
public void testEntityTypeIsValidValue() {
for (Object value : validValues) {
assertTrue(entityType.isValidValue(value), "value=" + value);
}
for (Object value : invalidValues) {
assertFalse(entityType.isValidValue(value), "value=" + value);
}
}
@Test
public void testEntityTypeGetNormalizedValue() {
assertNull(entityType.getNormalizedValue(null), "value=" + null);
for (Object value : validValues) {
if (value == null) {
continue;
}
Object normalizedValue = entityType.getNormalizedValue(value);
assertNotNull(normalizedValue, "value=" + value);
}
for (Object value : invalidValues) {
assertNull(entityType.getNormalizedValue(value), "value=" + value);
}
}
@Test
public void testEntityTypeValidateValue() {
List<String> messages = new ArrayList<>();
for (Object value : validValues) {
assertTrue(entityType.validateValue(value, "testObj", messages));
assertEquals(messages.size(), 0, "value=" + value);
}
for (Object value : invalidValues) {
assertFalse(entityType.validateValue(value, "testObj", messages));
assertTrue(messages.size() > 0, "value=" + value);
messages.clear();
}
}
@Test
public void testValidConstraints() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
List<AtlasEntityDef> entityDefs = new ArrayList<>();
String failureMsg = null;
entityDefs.add(createTableEntityDef());
entityDefs.add(createColumnEntityDef());
try {
ttr = typeRegistry.lockTypeRegistryForUpdate();
ttr.addTypes(entityDefs);
AtlasEntityType typeTable = ttr.getEntityTypeByName(TYPE_TABLE);
AtlasEntityType typeColumn = ttr.getEntityTypeByName(TYPE_COLUMN);
assertTrue(typeTable.getAttribute(ATTR_COLUMNS).isOwnedRef());
assertNull(typeTable.getAttribute(ATTR_COLUMNS).getInverseRefAttributeName());
assertFalse(typeColumn.getAttribute(ATTR_TABLE).isOwnedRef());
assertEquals(typeColumn.getAttribute(ATTR_TABLE).getInverseRefAttributeName(), ATTR_COLUMNS);
assertEquals(typeColumn.getAttribute(ATTR_TABLE).getInverseRefAttribute(), typeTable.getAttribute(ATTR_COLUMNS));
commit = true;
} catch (AtlasBaseException excp) {
failureMsg = excp.getMessage();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertNull(failureMsg, "failed to create types " + TYPE_TABLE + " and " + TYPE_COLUMN);
}
@Test
public void testConstraintInvalidOwnedRef_InvalidAttributeType() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
List<AtlasEntityDef> entityDefs = new ArrayList<>();
AtlasErrorCode errorCode = null;
entityDefs.add(createTableEntityDefWithOwnedRefOnInvalidType());
try {
ttr = typeRegistry.lockTypeRegistryForUpdate();
ttr.addTypes(entityDefs);
commit = true;
} catch (AtlasBaseException excp) {
errorCode = excp.getAtlasErrorCode();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_OWNED_REF_ATTRIBUTE_INVALID_TYPE,
"expected invalid constraint failure - missing refAttribute");
}
@Test
public void testConstraintInValidInverseRef_MissingParams() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
List<AtlasEntityDef> entityDefs = new ArrayList<>();
AtlasErrorCode errorCode = null;
entityDefs.add(createTableEntityDef());
entityDefs.add(createColumnEntityDefWithMissingInverseAttribute());
try {
ttr = typeRegistry.lockTypeRegistryForUpdate();
ttr.addTypes(entityDefs);
commit = true;
} catch (AtlasBaseException excp) {
errorCode = excp.getAtlasErrorCode();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_MISSING_PARAMS,
"expected invalid constraint failure - missing refAttribute");
}
@Test
public void testConstraintInValidInverseRef_InvalidAttributeTypeForInverseAttribute() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
List<AtlasEntityDef> entityDefs = new ArrayList<>();
AtlasErrorCode errorCode = null;
entityDefs.add(createTableEntityDef());
entityDefs.add(createColumnEntityDefWithInvaidAttributeTypeForInverseAttribute());
try {
ttr = typeRegistry.lockTypeRegistryForUpdate();
ttr.addTypes(entityDefs);
commit = true;
} catch (AtlasBaseException excp) {
errorCode = excp.getAtlasErrorCode();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_INVERSE_REF_ATTRIBUTE_INVALID_TYPE,
"expected invalid constraint failure - missing refAttribute");
}
@Test
public void testConstraintInValidInverseRef_InvalidAttributeType() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
List<AtlasEntityDef> entityDefs = new ArrayList<>();
AtlasErrorCode errorCode = null;
entityDefs.add(createTableEntityDef());
entityDefs.add(createColumnEntityDefWithInvalidInverseAttributeType());
try {
ttr = typeRegistry.lockTypeRegistryForUpdate();
ttr.addTypes(entityDefs);
commit = true;
} catch (AtlasBaseException excp) {
errorCode = excp.getAtlasErrorCode();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_INVERSE_REF_INVERSE_ATTRIBUTE_INVALID_TYPE,
"expected invalid constraint failure - invalid refAttribute type");
}
@Test
public void testConstraintInValidInverseRef_NonExistingAttribute() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
List<AtlasEntityDef> entityDefs = new ArrayList<>();
AtlasErrorCode errorCode = null;
entityDefs.add(createTableEntityDef());
entityDefs.add(createColumnEntityDefWithNonExistingInverseAttribute());
try {
ttr = typeRegistry.lockTypeRegistryForUpdate();
ttr.addTypes(entityDefs);
commit = true;
} catch (AtlasBaseException excp) {
errorCode = excp.getAtlasErrorCode();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_INVERSE_REF_INVERSE_ATTRIBUTE_NON_EXISTING,
"expected invalid constraint failure - non-existing refAttribute");
}
private static AtlasEntityType getEntityType(AtlasEntityDef entityDef) {
try {
return new AtlasEntityType(entityDef, ModelTestUtil.getTypesRegistry());
} catch (AtlasBaseException excp) {
return null;
}
}
private AtlasEntityDef createTableEntityDef() {
AtlasEntityDef table = new AtlasEntityDef(TYPE_TABLE);
AtlasAttributeDef attrName = new AtlasAttributeDef(ATTR_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING);
AtlasAttributeDef attrColumns = new AtlasAttributeDef(ATTR_COLUMNS,
AtlasBaseTypeDef.getArrayTypeName(TYPE_COLUMN));
attrColumns.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF));
table.addAttribute(attrName);
table.addAttribute(attrColumns);
return table;
}
private AtlasEntityDef createTableEntityDefWithOwnedRefOnInvalidType() {
AtlasEntityDef table = new AtlasEntityDef(TYPE_TABLE);
AtlasAttributeDef attrName = new AtlasAttributeDef(ATTR_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING);
attrName.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF));
table.addAttribute(attrName);
return table;
}
private AtlasEntityDef createColumnEntityDefWithMissingInverseAttribute() {
AtlasEntityDef column = new AtlasEntityDef(TYPE_COLUMN);
AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);
attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF));
column.addAttribute(attrTable);
return column;
}
private AtlasEntityDef createColumnEntityDefWithInvaidAttributeTypeForInverseAttribute() {
AtlasEntityDef column = new AtlasEntityDef(TYPE_COLUMN);
AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING);
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, ATTR_NAME);
attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
column.addAttribute(attrTable);
return column;
}
private AtlasEntityDef createColumnEntityDefWithNonExistingInverseAttribute() {
AtlasEntityDef column = new AtlasEntityDef(TYPE_COLUMN);
AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, "non-existing:" + ATTR_COLUMNS);
attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
column.addAttribute(attrTable);
return column;
}
private AtlasEntityDef createColumnEntityDefWithInvalidInverseAttributeType() {
AtlasEntityDef column = new AtlasEntityDef(TYPE_COLUMN);
AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, ATTR_NAME);
attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
column.addAttribute(attrTable);
return column;
}
private AtlasEntityDef createColumnEntityDef() {
AtlasEntityDef column = new AtlasEntityDef(TYPE_COLUMN);
AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, ATTR_COLUMNS);
attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
column.addAttribute(attrTable);
return column;
}
}