/*
* 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 2014-2015 ForgeRock AS
*/
package org.opends.server.types;
import static org.opends.server.types.AcceptRejectWarn.*;
import static org.testng.Assert.*;
import java.util.LinkedList;
import org.forgerock.i18n.LocalizableMessageBuilder;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.DirectoryServer;
import org.opends.server.tools.LDAPModify;
import org.testng.annotations.Test;
/**
* This class provides a set of test cases that cover the schema validation
* processing that should be performed on entries during add, modify, and
* modify DN operations.
*/
public class EntrySchemaCheckingTestCase
extends TypesTestCase
{
/**
* Ensures that the provided entry fails schema checking validation with
* strict compliance enabled, but will pass in a more relaxed configuration.
*
* @param e The entry to be tested.
*/
private void failOnlyForStrictEvaluation(Entry e)
{
try
{
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
DirectoryServer.setSingleStructuralObjectClassPolicy(REJECT);
assertFalse(e.conformsToSchema(null, false, true, true, invalidReason),
"Entry validation succeeded with REJECT policy");
DirectoryServer.setSingleStructuralObjectClassPolicy(WARN);
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
"Entry validation failed with WARN policy: " + invalidReason);
DirectoryServer.setSingleStructuralObjectClassPolicy(ACCEPT);
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
"Entry validation failed with ACCEPT policy: " + invalidReason);
}
finally
{
DirectoryServer.setSingleStructuralObjectClassPolicy(REJECT);
}
}
/**
* Ensures that the provided entry fails schema checking validation irrespective
* of relaxed compliance configured. Added due to unique niche case described
* in OPENDJ-1797
*
* @param e The entry to be tested.
*/
private void failAlwaysStrictEvaluation(Entry e)
{
try
{
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
DirectoryServer.setSingleStructuralObjectClassPolicy(REJECT);
assertFalse(e.conformsToSchema(null, false, true, true, invalidReason),
"Entry validation succeeded with REJECT policy");
DirectoryServer.setSingleStructuralObjectClassPolicy(WARN);
assertFalse(e.conformsToSchema(null, false, true, true, invalidReason),
"Entry validation failed with WARN policy: " + invalidReason);
DirectoryServer.setSingleStructuralObjectClassPolicy(ACCEPT);
assertFalse(e.conformsToSchema(null, false, true, true, invalidReason),
"Entry validation failed with ACCEPT policy: " + invalidReason);
}
finally
{
DirectoryServer.setSingleStructuralObjectClassPolicy(REJECT);
}
}
/**
* Tests schema checking for an entry with a valid single structural
* objectclass.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testValidSingleStructuralClass()
throws Exception
{
Entry e = TestCaseUtils.makeEntry(
"dn: dc=example,dc=com",
"objectClass: top",
"objectClass: domain",
"dc: example");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, true, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests schema checking for an entry (not covered by a DIT content rule)
* with a valid single structural objectclass as well as an auxiliary
* objectclass.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testValidSingleStructuralClassAndAuxiliaryClass()
throws Exception
{
Entry e = TestCaseUtils.makeEntry(
"dn: dc=example,dc=com",
"objectClass: top",
"objectClass: organization",
"objectClass: dcObject",
"dc: example",
"o: Example Org");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, true, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests schema checking for an entry that does not contain a structural
* objectclass.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testNoStructuralClass()
throws Exception
{
Entry e = TestCaseUtils.makeEntry(
"dn: dc=example,dc=com",
"objectClass: top",
"objectClass: dcObject",
"dc: example");
failOnlyForStrictEvaluation(e);
}
/**
* Tests schema checking for an entry that contains multiple structural
* objectclasses.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testMultipleStructuralClasses()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry e = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"objectClass: account",
"uid: test.user",
"givenName: Test",
"sn: User",
"cn: Test User");
failOnlyForStrictEvaluation(e);
}
/**
* Tests schema checking for an entry that contains an undefined objectclass
* with no other structural class.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testUndefinedStructuralObjectClass()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: xxxundefinedstructuralxxx",
"cn: test");
failAlwaysStrictEvaluation(e);
}
/**
* Tests schema checking for an entry that contains an undefined objectclass
* as well as a valid structural class.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testUndefinedAuxiliaryObjectClass()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: device",
"objectClass: xxxundefinedauxiliaryxxx",
"cn: test");
failAlwaysStrictEvaluation(e);
}
/**
* Tests schema checking for an entry that is missing an attribute required
* by its structural object class.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testMissingAttributeRequiredByStructuralClass()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testmissingatrequiredbystructuraloc-oid " +
"NAME 'testMissingATRequiredByStructuralOC' SUP top STRUCTURAL " +
"MUST ( cn $ description ) " +
"X-ORIGIN 'EntrySchemaCheckingTestCase')");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testMissingATRequiredByStructuralOC",
"cn: test");
assertFalse(e.conformsToSchema(null, false, true, true,
new LocalizableMessageBuilder()));
}
/**
* Tests schema checking for an entry that is missing an attribute required
* by an auxiliary object class.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testMissingAttributeRequiredByAuxiliaryClass()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testmissingatrequiredbyauxiliaryoc-oid " +
"NAME 'testMissingATRequiredByAuxiliaryOC' SUP top AUXILIARY " +
"MUST ( cn $ description ) " +
"X-ORIGIN 'EntrySchemaCheckingTestCase')");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: device",
"objectClass: testMissingATRequiredByAuxiliaryOC",
"cn: test");
assertFalse(e.conformsToSchema(null, false, true, true,
new LocalizableMessageBuilder()));
}
/**
* Tests schema checking for an entry that includes an attribute type that
* is not allowed by any of its object classes.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testDisallowedAttributeType()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testdisallowedattributetypeoc-oid " +
"NAME 'testDisallowedAttributeTypeOC' SUP top STRUCTURAL " +
"MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testDisallowedAttributeTypeOC",
"cn: test",
"description: foo");
assertFalse(e.conformsToSchema(null, false, true, true,
new LocalizableMessageBuilder()));
}
/**
* Tests schema checking for an entry that includes multiple values for a
* multivalued attribute.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testMultipleValuesForMultiValuedAttribute()
throws Exception
{
Entry e = TestCaseUtils.makeEntry(
"dn: o=test",
"objectClass: top",
"objectClass: organization",
"o: test",
"o: foo");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, true, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests schema checking for an entry that includes multiple values for a
* single-valued attribute.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testMultipleValuesForSingleValuedAttribute()
throws Exception
{
// The LDIF reader won't let us do this directly, so we have to hack around
// it.
Entry e = TestCaseUtils.makeEntry(
"dn: dc=example,dc=com",
"objectClass: top",
"objectClass: domain",
"dc: example");
e.addAttribute(Attributes.create("dc", "foo"), new LinkedList<ByteString>());
assertFalse(e.conformsToSchema(null, false, true, true, new LocalizableMessageBuilder()));
}
/**
* Tests schema checking for an entry that includes multiple values for a
* single-valued operational attribute.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testMultipleValuesForSingleValuedOperationalAttribute()
throws Exception
{
// The LDIF reader won't let us do this directly, so we have to hack around it.
Entry e = TestCaseUtils.makeEntry(
"dn: dc=example,dc=com",
"objectClass: top",
"objectClass: domain",
"dc: example");
AttributeType creatorsNameType = DirectoryServer.getAttributeTypeOrNull("creatorsname");
assertTrue(creatorsNameType.isOperational());
AttributeBuilder builder = new AttributeBuilder(creatorsNameType,
"creatorsName");
builder.add("cn=Directory Manager");
builder.add("cn=Another User");
e.addAttribute(builder.toAttribute(), new LinkedList<ByteString>());
assertFalse(e.conformsToSchema(null, false, true, true, new LocalizableMessageBuilder()));
}
/**
* Tests schema checking for an entry that contains structural and auxiliary
* objectclasses where the auxiliary class is allowed by a DIT content rule.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testAuxiliaryClassAllowedByDCR()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testauxiliaryclassallowedbydcroc-oid " +
"NAME 'testAuxiliaryClassAllowedByDCROC' SUP top STRUCTURAL " +
"MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')",
"objectClasses: ( testauxiliaryclassallowedbydcrocaux-oid " +
"NAME 'testAuxiliaryClassAllowedByDCROCAux' SUP top AUXILIARY " +
"MAY description X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: ditContentRules",
"ditContentRules: ( testauxiliaryclassallowedbydcroc-oid " +
"NAME 'testAuxiliaryClassAllowedByDCR' " +
"AUX testAuxiliaryClassAllowedByDCROCAux " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testAuxiliaryClassAllowedByDCROC",
"objectClass: testAuxiliaryClassAllowedByDCROCAux",
"cn: test");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests schema checking for an entry that contains structural and auxiliary
* objectclasses where the auxiliary class is not allowed by the associated
* DIT content rule.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testAuxiliaryClassNotAllowedByDCR()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testauxiliaryclassnotallowedbydcroc-oid " +
"NAME 'testAuxiliaryClassNotAllowedByDCROC' SUP top STRUCTURAL " +
"MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')",
"objectClasses: ( testauxiliaryclassnotallowedbydcrocaux-oid " +
"NAME 'testAuxiliaryClassNotAllowedByDCROCAux' SUP top " +
"AUXILIARY MAY description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: ditContentRules",
"ditContentRules: ( testauxiliaryclassnotallowedbydcroc-oid " +
"NAME 'testAuxiliaryClassNotAllowedByDCR' " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testAuxiliaryClassNotAllowedByDCROC",
"objectClass: testAuxiliaryClassNotAllowedByDCROCAux",
"cn: test");
failOnlyForStrictEvaluation(e);
}
/**
* Tests schema checking for an entry covered by a DIT content rule to
* ensure that attributes required by the DIT content rule are allowed even
* if not directly allowed by any of the entry's objectclasses.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testAllowAttributeRequiredByDCR()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testallowatrequiredbydcroc-oid " +
"NAME 'testAllowATRequiredByDCROC' SUP top STRUCTURAL " +
"MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: ditContentRules",
"ditContentRules: ( testallowatrequiredbydcroc-oid " +
"NAME 'testAllowATRequiredByDCR' MUST description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testAllowATRequiredByDCROC",
"cn: test",
"description: foo");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests schema checking for an entry covered by a DIT content rule to
* ensure that attributes required by the DIT content rule are required even
* if not directly allowed by any of the entry's objectclasses.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testRequireAttributeRequiredByDCR()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testrequireatrequiredbydcroc-oid " +
"NAME 'testRequireATRequiredByDCROC' SUP top STRUCTURAL " +
"MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: ditContentRules",
"ditContentRules: ( testrequireatrequiredbydcroc-oid " +
"NAME 'testRequireATRequiredByDCR' MUST description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testRequireATRequiredByDCROC",
"cn: test");
failOnlyForStrictEvaluation(e);
}
/**
* Tests schema checking for an entry for which there is a DIT content rule
* covering the structural objectclass but that DIT content rule is marked
* OBSOLETE. In this case, any attribute types required by the DIT content
* rule should not be required for the entry.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testDontRequireAttributeRequiredByObsoleteDCR()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testdontrequireatrequiredbyobsoletedcroc-oid " +
"NAME 'testDontRequireATRequiredByObsoleteDCROC' SUP top " +
"STRUCTURAL MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: ditContentRules",
"ditContentRules: ( testdontrequireatrequiredbyobsoletedcroc-oid " +
"NAME 'testDontRequireATRequiredByObsoleteDCR' OBSOLETE " +
"MUST description X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testDontRequireATRequiredByObsoleteDCROC",
"cn: test");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests schema checking for an entry covered by a DIT content rule to
* ensure that attributes allowed by the DIT content rule are allowed even
* if not directly allowed by any of the entry's objectclasses.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testAllowAttributeAllowedByDCR()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testallowatallowedbydcroc-oid " +
"NAME 'testAllowATAllowedByDCROC' SUP top STRUCTURAL " +
"MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: ditContentRules",
"ditContentRules: ( testallowatallowedbydcroc-oid " +
"NAME 'testAllowATAllowedByDCR' MAY description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testAllowATAllowedByDCROC",
"cn: test",
"description: foo");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests schema checking for an entry covered by a DIT content rule to
* ensure that attributes allowed by the DIT content rule are allowed but
* not required if they are not required by any of the associated object
* classes.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testDontRequireAttributeAllowedByDCR()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testdontrequireatallowedbydcroc-oid " +
"NAME 'testDontRequireATAllowedByDCROC' SUP top STRUCTURAL " +
"MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: ditContentRules",
"ditContentRules: ( testdontrequireatallowedbydcroc-oid " +
"NAME 'testDontRequireATAllowedByDCR' MAY description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testDontRequireATAllowedByDCROC",
"cn: test");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests schema checking for an entry covered by a DIT content rule to
* ensure that attributes prohibited by the DIT content rule are not allowed
* even if they are allowed by the associated object classes.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testDontAllowAttributeProhibitedByDCR()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testdontallowattributeprohibitedbydcroc-oid " +
"NAME 'testDontAllowAttributeProhibitedByDCROC' SUP top " +
"STRUCTURAL MUST cn MAY description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: ditContentRules",
"ditContentRules: ( testdontallowattributeprohibitedbydcroc-oid " +
"NAME 'testDontAllowAttributeProhibitedByDCR' NOT description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testDontAllowAttributeProhibitedByDCROC",
"cn: test",
"description: foo");
failOnlyForStrictEvaluation(e);
}
/**
* Tests that an entry covered by a name form will be accepted if its
* single-valued RDN component is compliant with that name form.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testSatisfiesSingleValuedNameForm()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testsatisfiessinglevaluednameformoc-oid " +
"NAME 'testSatisfiesSingleValuedNameFormOC' SUP top STRUCTURAL " +
"MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: nameForms",
"nameForms: ( testsatisfiessinglevaluednameform-oid " +
"NAME 'testSatisfiesSingleValuedNameForm' " +
"OC testSatisfiesSingleValuedNameFormOC MUST cn " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testSatisfiesSingleValuedNameFormOC",
"cn: test");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests that an entry covered by a name form will be rejected if its
* single-valued RDN component violates that name form.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testViolatesSingleValuedNameForm()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testviolatessinglevaluednameformoc-oid " +
"NAME 'testViolatesSingleValuedNameFormOC' SUP top STRUCTURAL " +
"MUST cn MAY description X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: nameForms",
"nameForms: ( testviolatessinglevaluednameform-oid " +
"NAME 'testViolatesSingleValuedNameForm' " +
"OC testViolatesSingleValuedNameFormOC MUST cn " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: description=foo,o=test",
"objectClass: top",
"objectClass: testViolatesSingleValuedNameFormOC",
"cn: test",
"description: foo");
failOnlyForStrictEvaluation(e);
}
/**
* Tests that an entry covered by a name form will be rejected if its
* multivalued RDN component violates that name form which only allows a
* single value.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testMVViolatesSingleValuedNameForm()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testmvviolatessinglevaluednameformoc-oid " +
"NAME 'testMVViolatesSingleValuedNameFormOC' SUP top STRUCTURAL " +
"MUST cn MAY description X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: nameForms",
"nameForms: ( testmvviolatessinglevaluednameform-oid " +
"NAME 'testMVViolatesSingleValuedNameForm' " +
"OC testMVViolatesSingleValuedNameFormOC MUST cn " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test+description=foo,o=test",
"objectClass: top",
"objectClass: testMVViolatesSingleValuedNameFormOC",
"cn: test",
"description: foo");
failOnlyForStrictEvaluation(e);
}
/**
* Tests that an entry covered by a name form will not be rejected if its
* single-valued RDN component violates that name form but the name form is
* declared OBSOLETE.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testViolatesSingleValuedObsoleteNameForm()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testviolatessinglevaluedobsoletenameformoc-oid " +
"NAME 'testViolatesSingleValuedObsoleteNameFormOC' SUP top " +
"STRUCTURAL MUST cn MAY description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: nameForms",
"nameForms: ( testviolatessinglevaluedobsoletenameform-oid " +
"NAME 'testViolatesSingleValuedObsoleteNameForm' OBSOLETE " +
"OC testViolatesSingleValuedObsoleteNameFormOC MUST cn " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: description=foo,o=test",
"objectClass: top",
"objectClass: testViolatesSingleValuedObsoleteNameFormOC",
"cn: test",
"description: foo");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests that an entry covered by a name form will be accepted if its
* multivalued RDN component is compliant with that name form which requires
* multiple values.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testSatisfiesRequiredMultiValuedNameForm()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testsatisfiesrequiredmultivaluednameformoc-oid " +
"NAME 'testSatisfiesRequiredMultiValuedNameFormOC' SUP top " +
"STRUCTURAL MUST cn MAY description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: nameForms",
"nameForms: ( testsatisfiesrequiredmultivaluednameform-oid " +
"NAME 'testSatisfiesRequiredMultiValuedNameForm' " +
"OC testSatisfiesRequiredMultiValuedNameFormOC " +
"MUST ( cn $ description ) " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test+description=foo,o=test",
"objectClass: top",
"objectClass: testSatisfiesRequiredMultiValuedNameFormOC",
"cn: test",
"description: foo");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests that an entry covered by a name form will be accepted if its
* single-valued RDN component only contains one of the multiple required
* attribute types.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testViolatesRequiredMultiValuedNameForm()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testviolatesrequiredmultivaluednameformoc-oid " +
"NAME 'testViolatesRequiredMultiValuedNameFormOC' SUP top " +
"STRUCTURAL MUST cn MAY description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: nameForms",
"nameForms: ( testviolatesrequiredmultivaluednameform-oid " +
"NAME 'testViolatesRequiredMultiValuedNameForm' " +
"OC testViolatesRequiredMultiValuedNameFormOC " +
"MUST ( cn $ description ) " +
"X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testViolatesRequiredMultiValuedNameFormOC",
"cn: test",
"description: foo");
failOnlyForStrictEvaluation(e);
}
/**
* Tests that an entry covered by a name form will be accepted if its
* single-valued RDN component is compliant with that name form which requires
* one value but allows other values.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testSVSatisfiesOptionalMultiValuedNameForm()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testsvsatisfiesoptionalmultivaluednameformoc-oid " +
"NAME 'testSVSatisfiesOptionalMultiValuedNameFormOC' SUP top " +
"STRUCTURAL MUST cn MAY description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: nameForms",
"nameForms: ( testsvsatisfiesoptionalmultivaluednameform-oid " +
"NAME 'testSVSatisfiesOptionalMultiValuedNameForm' " +
"OC testSVSatisfiesOptionalMultiValuedNameFormOC MUST cn " +
"MAY description X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test,o=test",
"objectClass: top",
"objectClass: testSVSatisfiesOptionalMultiValuedNameFormOC",
"cn: test",
"description: foo");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests that an entry covered by a name form will be accepted if its
* multivalued RDN component is compliant with that name form which requires
* one value but allows other values.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testMVSatisfiesOptionalMultiValuedNameForm()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testmvsatisfiesoptionalmultivaluednameformoc-oid " +
"NAME 'testMVSatisfiesOptionalMultiValuedNameFormOC' SUP top " +
"STRUCTURAL MUST cn MAY description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: nameForms",
"nameForms: ( testmvsatisfiesoptionalmultivaluednameform-oid " +
"NAME 'testMVSatisfiesOptionalMultiValuedNameForm' " +
"OC testMVSatisfiesOptionalMultiValuedNameFormOC MUST cn " +
"MAY description X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=test+description=foo,o=test",
"objectClass: top",
"objectClass: testMVSatisfiesOptionalMultiValuedNameFormOC",
"cn: test",
"description: foo");
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
invalidReason.toString());
}
/**
* Tests that an entry covered by a name form will be accepted if its
* single-valued RDN component violates that name form which requires
* one value but allows other values.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testSVViolatesOptionalMultiValuedNameForm()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testsvviolatesoptionalmultivaluednameformoc-oid " +
"NAME 'testSVViolatesOptionalMultiValuedNameFormOC' SUP top " +
"STRUCTURAL MUST cn MAY description " +
"X-ORIGIN 'EntrySchemaCheckingTestCase')",
"-",
"add: nameForms",
"nameForms: ( testsvviolatesoptionalmultivaluednameform-oid " +
"NAME 'testSVViolatesOptionalMultiValuedNameForm' " +
"OC testSVViolatesOptionalMultiValuedNameFormOC MUST cn " +
"MAY description X-ORIGIN 'EntrySchemaCheckingTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: description=foo,o=test",
"objectClass: top",
"objectClass: testSVViolatesOptionalMultiValuedNameFormOC",
"cn: test",
"description: foo");
failOnlyForStrictEvaluation(e);
}
/**
* Performs various tests to ensure that the server appropriately enforces DIT
* structure rule constraints.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testDITStructureRuleConstraints()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testditstructureruleconstraintssupoc-oid " +
"NAME 'testDITStructureRuleConstraintsSupOC' SUP top " +
"STRUCTURAL MUST ou X-ORIGIN 'SchemaBackendTestCase')",
"objectClasses: ( testditstructureruleconstraintssuboc-oid " +
"NAME 'testDITStructureRuleConstraintsSubOC' SUP top " +
"STRUCTURAL MUST cn X-ORIGIN 'SchemaBackendTestCase')",
"-",
"add: nameForms",
"nameForms: ( testditstructureruleconstraintsupsnf-oid " +
"NAME 'testDITStructureRuleConstraintsSupNF' " +
"OC testDITStructureRuleConstraintsSupOC MUST ou " +
"X-ORIGIN 'SchemaBackendTestCase' )",
"nameForms: ( testditstructureruleconstraintsubsnf-oid " +
"NAME 'testDITStructureRuleConstraintsSubNF' " +
"OC testDITStructureRuleConstraintsSubOC MUST cn " +
"X-ORIGIN 'SchemaBackendTestCase' )",
"-",
"add: ditStructureRules",
"ditStructureRules: ( 999014 " +
"NAME 'testDITStructureRuleConstraintsSup' " +
"FORM testDITStructureRuleConstraintsSupNF " +
"X-ORIGIN 'SchemaBackendTestCase' )",
"ditStructureRules: ( 999015 " +
"NAME 'testDITStructureRuleConstraintsSub' " +
"FORM testDITStructureRuleConstraintsSubNF SUP 999014 " +
"X-ORIGIN 'SchemaBackendTestCase' )");
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
Entry e = TestCaseUtils.makeEntry(
"dn: cn=child,ou=parent,o=test",
"objectClass: top",
"objectClass: testDITStructureRuleConstraintsSubOC",
"cn: child");
failOnlyForStrictEvaluation(e);
path = TestCaseUtils.createTempFile(
"dn: ou=parent,o=test",
"changetype: add",
"objectClass: top",
"objectClass: testDITStructureRuleConstraintsSupOC",
"ou: parent");
args = new String[]
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
assertTrue(e.conformsToSchema(null, false, true, true, invalidReason),
invalidReason.toString());
e = TestCaseUtils.makeEntry(
"dn: cn=not below valid parent,o=test",
"objectClass: top",
"objectClass: testDITStructureRuleConstraintsSubOC",
"cn: not below valid parent");
failOnlyForStrictEvaluation(e);
e = TestCaseUtils.makeEntry(
"dn: cn=invalid entry below parent covered by DSR,ou=parent,o=test",
"objectClass: top",
"objectClass: device",
"cn: invalid entry below parent covered by DSR");
invalidReason = new LocalizableMessageBuilder();
failOnlyForStrictEvaluation(e);
}
/**
* Tests schema checking for an entry that includes an attribute not
* defined in any objectClasses but the subtypes of the attribute are.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test
public void testInvalidSuperiorAttribute()
throws Exception
{
// The LDIF reader won't let us do this directly, so we have to hack around
// it.
Entry e = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"objectClass: account",
"uid: test.user",
"givenName: Test",
"sn: User",
"cn: Test User");
e.addAttribute(Attributes.create("name", "foo"), new LinkedList<ByteString>());
assertFalse(e.conformsToSchema(null, false, true, true, new LocalizableMessageBuilder()));
}
}