ValidateConfigDefinitionsTest.java revision 530e312594f469609337996570cf0ea504554a68
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2008 Sun Microsystems, Inc.
* Portions copyright 2011-2015 ForgeRock AS
*/
package org.opends.server.admin;
import static org.opends.server.util.ServerConstants.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.opends.server.DirectoryServerTestCase;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.AttributeType;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.Schema;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class ValidateConfigDefinitionsTest extends DirectoryServerTestCase {
@BeforeClass
public void startServer() throws Exception {
TestCaseUtils.startServer();
}
/**
* Returns all AbstractManagedObjectDefinition objects that are
* defined in
*/
@DataProvider
public Object[][] enumrateManageObjectDefns() throws Exception {
TopCfgDefn topCfgDefn = TopCfgDefn.getInstance();
List<AbstractManagedObjectDefinition<?,?>> allCfgDefns =
new ArrayList<AbstractManagedObjectDefinition<?,?>>(topCfgDefn.getAllChildren());
Object[][] params = new Object[allCfgDefns.size()][];
for (int i = 0; i < params.length; i++) {
params[i] = new Object[]{allCfgDefns.get(i)};
}
return params;
}
// Exceptions to config objects having a differnt objectclass
private static final List<String> CLASS_OBJECT_CLASS_EXCEPTIONS =
Arrays.asList(
"org.opends.server.admin.std.meta.RootCfgDefn",
"org.opends.server.admin.std.meta.GlobalCfgDefn"
);
@Test(dataProvider="enumrateManageObjectDefns")
public void validateConfigObjectDefinitions(AbstractManagedObjectDefinition<?, ?> objectDef) {
String objName = objectDef.getName();
StringBuilder errors = new StringBuilder();
Collection<PropertyDefinition<?>> allDefinitions =
objectDef.getAllPropertyDefinitions();
LDAPProfile ldapProfile = LDAPProfile.getInstance();
String ldapObjectclassName = ldapProfile.getObjectClass(objectDef);
if (ldapObjectclassName == null) {
errors.append("There is no objectclass definition for configuration object " + objName);
} else {
String expectedObjectClass = "ds-cfg-" + objName;
if (!ldapObjectclassName.equals(expectedObjectClass) &&
!CLASS_OBJECT_CLASS_EXCEPTIONS.contains(objectDef.getClass().getName())) {
errors.append("For config object " + objName +
", the LDAP objectclass must be " + expectedObjectClass +
" instead of " + ldapObjectclassName).append(EOL + EOL);
}
}
ObjectClass configObjectClass = DirectoryServer.getSchema().getObjectClass(ldapObjectclassName.toLowerCase());;
for (PropertyDefinition<?> propDef: allDefinitions) {
validatePropertyDefinition(objectDef, configObjectClass, propDef, errors);
}
if (errors.length() > 0) {
Assert.fail("The configuration definition for " + objectDef.getName() + " has the following problems: " + EOL +
errors.toString());
}
}
// Exceptions to properties ending in -class being exactly 'java-class'.
private static final List<String> CLASS_PROPERTY_EXCEPTIONS =
Arrays.asList(
// e.g. "prop-name-ending-with-class"
);
// Exceptions to properties ending in -enabled being exactly 'enabled'.
private static final List<String> ENABLED_PROPERTY_EXCEPTIONS =
Arrays.asList(
"index-filter-analyzer-enabled",
"subordinate-indexes-enabled"
// e.g. "prop-name-ending-with-enabled"
);
// Exceptions to properties not starting with the name of their config object
private static final List<String> OBJECT_PREFIX_PROPERTY_EXCEPTIONS =
Arrays.asList(
"backend-id",
"plugin-type",
"replication-server-id",
"network-group-id",
"workflow-id",
"workflow-element-id",
"workflow-element"
// e.g. "prop-name-starting-with-object-prefix"
);
private void validatePropertyDefinition(AbstractManagedObjectDefinition<?, ?> objectDef,
ObjectClass configObjectClass,
PropertyDefinition<?> propDef,
StringBuilder errors) {
String objName = objectDef.getName();
String propName = propDef.getName();
// We want class properties to be exactly java-class
if (propName.endsWith("-class") &&
!propName.equals("java-class") &&
!CLASS_PROPERTY_EXCEPTIONS.contains(propName))
{
errors.append("The " + propName + " property on config object " + objName +
" should probably be java-class. If not, then add " +
propName + " to the CLASS_PROPERTY_EXCEPTIONS array in " +
ValidateConfigDefinitionsTest.class.getName() + " to suppress" +
" this warning.");
}
// We want enabled properties to be exactly enabled
if (propName.endsWith("-enabled") && !ENABLED_PROPERTY_EXCEPTIONS.contains(propName))
{
errors.append("The " + propName + " property on config object " + objName +
" should probably be just 'enabled'. If not, then add " +
propName + " to the ENABLED_PROPERTY_EXCEPTIONS array in " +
ValidateConfigDefinitionsTest.class.getName() + " to suppress" +
" this warning.");
}
// It's redundant for properties to be prefixed with the name of their objecty
if (propName.startsWith(objName) && !propName.equals(objName) &&
!OBJECT_PREFIX_PROPERTY_EXCEPTIONS.contains(propName))
{
errors.append("The " + propName + " property on config object " + objName +
" should not be prefixed with the name of the config object because" +
" this is redundant. If you disagree, then add " +
propName + " to the OBJECT_PREFIX_PROPERTY_EXCEPTIONS array in " +
ValidateConfigDefinitionsTest.class.getName() + " to suppress" +
" this warning.");
}
LDAPProfile ldapProfile = LDAPProfile.getInstance();
String ldapAttrName = ldapProfile.getAttributeName(objectDef, propDef);
// LDAP attribute name is consistent with the property name
String expectedLdapAttr = "ds-cfg-" + propName;
if (!ldapAttrName.equals(expectedLdapAttr)) {
errors.append("For the " + propName + " property on config object " + objName +
", the LDAP attribute must be " + expectedLdapAttr + " instead of " + ldapAttrName).append(EOL + EOL);
}
Schema schema = DirectoryServer.getSchema();
AttributeType attrType = schema.getAttributeType(ldapAttrName.toLowerCase());
// LDAP attribute exists
if (attrType == null) {
errors.append(propName + " property on config object " + objName + " is declared" +
" to use ldap attribute " + ldapAttrName + ", but this attribute is not in the schema ").append(EOL + EOL);
} else {
// LDAP attribute is multivalued if the property is multivalued
if (propDef.hasOption(PropertyOption.MULTI_VALUED) && attrType.isSingleValue()) {
errors.append(propName + " property on config object " + objName + " is declared" +
" as multi-valued, but the corresponding ldap attribute " + ldapAttrName +
" is declared as single-valued.").append(EOL + EOL);
}
if (configObjectClass != null) {
// If it's mandatory in the schema, it must be mandatory on the config property
Set<AttributeType> mandatoryAttributes = configObjectClass.getRequiredAttributeChain();
if (mandatoryAttributes.contains(attrType) && !propDef.hasOption(PropertyOption.MANDATORY)) {
errors.append(propName + " property on config object " + objName + " is not declared" +
" as mandatory even though the corresponding ldap attribute " + ldapAttrName +
" is declared as mandatory in the schema.").append(EOL + EOL);
}
Set<AttributeType> allowedAttributes = new HashSet<AttributeType>(mandatoryAttributes);
allowedAttributes.addAll(configObjectClass.getOptionalAttributeChain());
if (!allowedAttributes.contains(attrType)) {
errors.append(propName + " property on config object " + objName + " has" +
" the corresponding ldap attribute " + ldapAttrName +
", but this attribute is not an allowed attribute on the configuration " +
" object's objectclass " + configObjectClass.getNameOrOID()).append(EOL + EOL);
}
}
}
}
}