From a7b900a8498272e3e7f59b4a19521efb635d3434 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Fri, 24 Jun 2011 23:01:52 +0000
Subject: [PATCH] Fix for OPENDJ-205: Add support for rejecting and skipping records to the LDIF readers

---
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java                      |   63 
 opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/schema/EntrySchemaCheckingTestCase.java | 1905 +++++++++++++++++++++++++++++----------------------------
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java               |    5 
 3 files changed, 999 insertions(+), 974 deletions(-)

diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
index 8f7e96e..4fa8f11 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
@@ -3141,7 +3141,8 @@
         // content rule.
         if (checkDITContentRule)
         {
-          if (objectClass.getObjectClassType() == ObjectClassType.AUXILIARY)
+          if (objectClass.getObjectClassType() == ObjectClassType.AUXILIARY
+              && !ditContentRule.getAuxiliaryClasses().contains(objectClass))
           {
             if (errorMessages != null)
             {
@@ -3161,11 +3162,11 @@
         // present.
         if (checkObjectClasses)
         {
-          for (final AttributeType t : objectClass.getRequiredAttributes())
+          for (final AttributeType t : objectClass.getDeclaredRequiredAttributes())
           {
             final Attribute a = Attributes.emptyAttribute(AttributeDescription
                 .create(t));
-            if (entry.containsAttribute(a, null))
+            if (!entry.containsAttribute(a, null))
             {
               if (errorMessages != null)
               {
@@ -3191,7 +3192,7 @@
         {
           final Attribute a = Attributes.emptyAttribute(AttributeDescription
               .create(t));
-          if (entry.containsAttribute(a, null))
+          if (!entry.containsAttribute(a, null))
           {
             if (errorMessages != null)
             {
@@ -3284,37 +3285,37 @@
               }
             }
           }
+        }
 
-          // Check attributes contain an appropriate number of values.
-          if (checkAttributeValues)
+        // Check all attributes contain an appropriate number of values.
+        if (checkAttributeValues)
+        {
+          final int sz = attribute.size();
+
+          if (sz == 0)
           {
-            final int sz = attribute.size();
-
-            if (sz == 0)
+            if (errorMessages != null)
             {
-              if (errorMessages != null)
-              {
-                final LocalizableMessage message = ERR_ENTRY_SCHEMA_AT_EMPTY_ATTRIBUTE
-                    .get(entry.getName().toString(), t.getNameOrOID());
-                errorMessages.add(message);
-              }
-              if (policy.checkAttributeValues().isReject())
-              {
-                return false;
-              }
+              final LocalizableMessage message = ERR_ENTRY_SCHEMA_AT_EMPTY_ATTRIBUTE
+              .get(entry.getName().toString(), t.getNameOrOID());
+              errorMessages.add(message);
             }
-            else if (sz > 1 && t.isSingleValue())
+            if (policy.checkAttributeValues().isReject())
             {
-              if (errorMessages != null)
-              {
-                final LocalizableMessage message = ERR_ENTRY_SCHEMA_AT_SINGLE_VALUED_ATTRIBUTE
-                    .get(entry.getName().toString(), t.getNameOrOID());
-                errorMessages.add(message);
-              }
-              if (policy.checkAttributeValues().isReject())
-              {
-                return false;
-              }
+              return false;
+            }
+          }
+          else if (sz > 1 && t.isSingleValue())
+          {
+            if (errorMessages != null)
+            {
+              final LocalizableMessage message = ERR_ENTRY_SCHEMA_AT_SINGLE_VALUED_ATTRIBUTE
+              .get(entry.getName().toString(), t.getNameOrOID());
+              errorMessages.add(message);
+            }
+            if (policy.checkAttributeValues().isReject())
+            {
+              return false;
             }
           }
         }
@@ -3388,7 +3389,7 @@
       for (final AVA ava : rdn)
       {
         final AttributeType t = ava.getAttributeType();
-        if (nameForm.isRequiredOrOptional(t))
+        if (!nameForm.isRequiredOrOptional(t))
         {
           if (nameFormWarnings != null)
           {
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
index 3e4b81b..d9613e1 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
@@ -2233,6 +2233,11 @@
       throws ConflictingSchemaElementException, NullPointerException
   {
     Validator.ensureNotNull(schema);
+
+    // All of the schema elements must be duplicated because validation will
+    // cause them to update all their internal references which, although
+    // unlikely, may be different in the new schema.
+
     for (final Syntax syntax : schema.getSyntaxes())
     {
       addSyntax(syntax.duplicate(), overwrite);
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/schema/EntrySchemaCheckingTestCase.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/schema/EntrySchemaCheckingTestCase.java
index ef39b3e..1b04bc5 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/schema/EntrySchemaCheckingTestCase.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/schema/EntrySchemaCheckingTestCase.java
@@ -32,7 +32,8 @@
 import static org.forgerock.opendj.ldap.schema.SchemaValidationPolicy.defaultPolicy;
 import static org.forgerock.opendj.ldap.schema.SchemaValidationPolicy.ignoreAll;
 
-import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.opendj.ldap.DN;
@@ -52,401 +53,73 @@
 @Test
 public class EntrySchemaCheckingTestCase extends SchemaTestCase
 {
-  /**
-   * Ensures that the provided entry fails schema checking validation with
-   * strict compliance enabled, but will pass in a more relaxed configuration.
-   * <p>
-   * Uses the default schema.
-   *
-   * @param e
-   *          The entry to be tested.
-   */
-  private void failOnlyForStrictEvaluation(Entry e)
-  {
-    failOnlyForStrictEvaluation(e, Schema.getDefaultSchema());
-  }
-
-
 
   /**
-   * 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.
-   * @param schema
-   *          The schema to use.
-   */
-  private void failOnlyForStrictEvaluation(Entry e, Schema schema)
-  {
-    assertThat(
-        conformsToSchema(e, schema, defaultPolicy()
-            .requireSingleStructuralObjectClass(Policy.IGNORE), null)).isTrue();
-    assertThat(
-        conformsToSchema(e, schema, defaultPolicy()
-            .requireSingleStructuralObjectClass(Policy.WARN), null)).isTrue();
-    assertThat(
-        conformsToSchema(e, schema, defaultPolicy()
-            .requireSingleStructuralObjectClass(Policy.REJECT), null))
-        .isFalse();
-  }
-
-
-
-  /**
-   * Tests schema checking for an entry with a valid single structural
-   * objectclass.
+   * 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(enabled = false)
-  public void testValidSingleStructuralClass() throws Exception
+  @Test
+  public void testAllowAttributeAllowedByDCR() throws Exception
   {
-    // @formatter:off
-    Entry e = newEntry(
-        "dn: dc=example,dc=com",
-        "objectClass: top",
-        "objectClass: domain",
-        "dc: example");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, defaultPolicy(), null)).isTrue();
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testValidSingleStructuralClassAndAuxiliaryClass()
-      throws Exception
-  {
-    // @formatter:off
-    Entry e = newEntry(
-        "dn: dc=example,dc=com",
-        "objectClass: top",
-        "objectClass: organization",
-        "objectClass: dcObject",
-        "dc: example",
-        "o: Example Org");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, defaultPolicy(), null)).isTrue();
-  }
-
-
-
-  /**
-   * Tests schema checking for an entry that does not contain a structural
-   * objectclass.
-   *
-   * @throws Exception
-   *           If an unexpected problem occurs.
-   */
-  @Test(enabled = false)
-  public void testNoStructuralClass() throws Exception
-  {
-    // @formatter:off
-    Entry e = newEntry(
-        "dn: dc=example,dc=com",
-        "objectClass: top",
-        "objectClass: dcObject",
-        "dc: example");
-    // @formatter:on
-
-    failOnlyForStrictEvaluation(e);
-  }
-
-
-
-  /**
-   * Tests schema checking for an entry that contains multiple structural
-   * objectclasses.
-   *
-   * @throws Exception
-   *           If an unexpected problem occurs.
-   */
-  @Test(enabled = false)
-  public void testMultipleStructuralClasses() throws Exception
-  {
-    // @formatter:off
-    Entry e = newEntry(
-        "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");
-    // @formatter:on
-
-    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
-  {
-    // @formatter:off
-    Entry e = newEntry(
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: xxxundefinedstructuralxxx",
-        "cn: test");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, defaultPolicy(), null)).isFalse();
-  }
-
-
-
-  /**
-   * 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
-  {
-    // @formatter:off
-    Entry e = newEntry(
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: device",
-        "objectClass: xxxundefinedauxiliaryxxx",
-        "cn: test");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, defaultPolicy(), null)).isFalse();
-  }
-
-
-
-  /**
-   * 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
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
         .addObjectClass(
-            "( testmissingatrequiredbystructuraloc-oid "
-                + "NAME 'testMissingATRequiredByStructuralOC' SUP top STRUCTURAL "
-                + "MUST ( cn $ description ) "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: testMissingATRequiredByStructuralOC",
-        "cn: test");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isFalse();
-  }
-
-
-
-  private Entry newEntry(String... ldif)
-  {
-    return newEntry(Schema.getDefaultSchema(), ldif);
-  }
-
-
-
-  private Entry newEntry(Schema schema, String... ldif)
-  {
-    try
-    {
-      return new LDIFEntryReader(ldif).setSchema(schema).readEntry();
-    }
-    catch (Exception e)
-    {
-      throw new IllegalArgumentException(e);
-    }
-  }
-
-
-
-  /**
-   * 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
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testmissingatrequiredbyauxiliaryoc-oid "
-                + "NAME 'testMissingATRequiredByAuxiliaryOC' SUP top AUXILIARY "
-                + "MUST ( cn $ description ) "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: device",
-        "objectClass: testMissingATRequiredByAuxiliaryOC",
-        "cn: test");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isFalse();
-  }
-
-
-
-  /**
-   * 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
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testdisallowedattributetypeoc-oid "
-                + "NAME 'testDisallowedAttributeTypeOC' SUP top STRUCTURAL "
+            "( testallowatallowedbydcroc-oid "
+                + "NAME 'testAllowATAllowedByDCROC' SUP top STRUCTURAL "
                 + "MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .toSchema();
+        .addDITContentRule(
+            "( testallowatallowedbydcroc-oid "
+                + "NAME 'testAllowATAllowedByDCR' MAY description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
 
     // @formatter:off
-    Entry e = newEntry(schema,
+    final Entry e = newEntry(schema,
         "dn: cn=test,o=test",
         "objectClass: top",
-        "objectClass: testDisallowedAttributeTypeOC",
+        "objectClass: testAllowATAllowedByDCROC",
         "cn: test",
         "description: foo");
     // @formatter:on
 
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isFalse();
-  }
-
-
-
-  private boolean conformsToSchema(final Entry entry,
-      final SchemaValidationPolicy policy,
-      final Collection<LocalizableMessage> errorMessages)
-  {
-    return conformsToSchema(entry, Schema.getDefaultSchema(), policy,
-        errorMessages);
-  }
-
-
-
-  private boolean conformsToSchema(final Entry entry, final Schema schema,
-      final SchemaValidationPolicy policy,
-      final Collection<LocalizableMessage> errorMessages)
-  {
-    return schema.validateEntry(entry, policy, errorMessages);
+    assertConformsToSchema(e, schema, defaultPolicy());
   }
 
 
 
   /**
-   * Tests schema checking for an entry that includes multiple values for a
-   * multivalued attribute.
+   * 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(enabled = false)
-  public void testMultipleValuesForMultiValuedAttribute() throws Exception
+  @Test
+  public void testAllowAttributeRequiredByDCR() throws Exception
   {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testallowatrequiredbydcroc-oid "
+                + "NAME 'testAllowATRequiredByDCROC' SUP top STRUCTURAL "
+                + "MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .addDITContentRule(
+            "( testallowatrequiredbydcroc-oid "
+                + "NAME 'testAllowATRequiredByDCR' MUST description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
+
     // @formatter:off
-    Entry e = newEntry(
-        "dn: o=test",
+    final Entry e = newEntry(schema,
+        "dn: cn=test,o=test",
         "objectClass: top",
-        "objectClass: organization",
-        "o: test",
-        "o: foo");
+        "objectClass: testAllowATRequiredByDCROC",
+        "cn: test",
+        "description: foo");
     // @formatter:on
 
-    assertThat(conformsToSchema(e, defaultPolicy(), null)).isTrue();
-  }
-
-
-
-  /**
-   * 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
-  {
-    // @formatter:off
-    Entry e = newEntry(
-        "dn: dc=example,dc=com",
-        "objectClass: top",
-        "objectClass: domain",
-        "dc: example",
-        "dc: foo");
-    // @formatter:on
-
-    assertThat(
-        conformsToSchema(e, ignoreAll().checkAttributeValues(Policy.REJECT),
-            null)).isFalse();
-  }
-
-
-
-  /**
-   * Tests schema checking for an entry that includes multiple values for a
-   * single-valued operational attribute.
-   *
-   * @throws Exception
-   *           If an unexpected problem occurs.
-   */
-  @Test(enabled = false)
-  public void testMultipleValuesForSingleValuedOperationalAttribute()
-      throws Exception
-  {
-    // @formatter:off
-    Entry e = newEntry(
-        "dn: dc=example,dc=com",
-        "objectClass: top",
-        "objectClass: domain",
-        "dc: example",
-        "creatorsName: cn=Directory Manager",
-        "creatorsName: cn=Another Manager");
-    // @formatter:on
-
-    assertThat(
-        conformsToSchema(e, ignoreAll().checkAttributeValues(Policy.REJECT),
-            null)).isFalse();
+    assertConformsToSchema(e, schema, defaultPolicy());
   }
 
 
@@ -458,10 +131,10 @@
    * @throws Exception
    *           If an unexpected problem occurs.
    */
-  @Test(enabled = false)
+  @Test
   public void testAuxiliaryClassAllowedByDCR() throws Exception
   {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
         .addObjectClass(
             "( testauxiliaryclassallowedbydcroc-oid "
                 + "NAME 'testAuxiliaryClassAllowedByDCROC' SUP top STRUCTURAL "
@@ -478,7 +151,7 @@
                 + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
 
     // @formatter:off
-    Entry e = newEntry(schema,
+    final Entry e = newEntry(schema,
         "dn: cn=test,o=test",
         "objectClass: top",
         "objectClass: testAuxiliaryClassAllowedByDCROC",
@@ -486,7 +159,7 @@
         "cn: test");
     // @formatter:on
 
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isTrue();
+    assertConformsToSchema(e, schema, defaultPolicy());
   }
 
 
@@ -499,10 +172,10 @@
    * @throws Exception
    *           If an unexpected problem occurs.
    */
-  @Test(enabled = false)
+  @Test
   public void testAuxiliaryClassNotAllowedByDCR() throws Exception
   {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
         .addObjectClass(
             "( testauxiliaryclassnotallowedbydcroc-oid "
                 + "NAME 'testAuxiliaryClassNotAllowedByDCROC' SUP top STRUCTURAL "
@@ -518,7 +191,7 @@
                 + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
 
     // @formatter:off
-    Entry e = newEntry(schema,
+    final Entry e = newEntry(schema,
         "dn: cn=test,o=test",
         "objectClass: top",
         "objectClass: testAuxiliaryClassNotAllowedByDCROC",
@@ -526,552 +199,44 @@
         "cn: test");
     // @formatter:on
 
-    failOnlyForStrictEvaluation(e, schema);
+    assertDoesNotConformToSchema(e, schema, defaultPolicy());
+
+    e.removeAttribute("objectClass", "testAuxiliaryClassNotAllowedByDCROCAux");
+    assertConformsToSchema(e, schema, defaultPolicy());
   }
 
 
 
   /**
-   * 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.
+   * 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(enabled = false)
-  public void testAllowAttributeRequiredByDCR() throws Exception
+  @Test
+  public void testDisallowedAttributeType() throws Exception
   {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
         .addObjectClass(
-            "( testallowatrequiredbydcroc-oid "
-                + "NAME 'testAllowATRequiredByDCROC' SUP top STRUCTURAL "
+            "( testdisallowedattributetypeoc-oid "
+                + "NAME 'testDisallowedAttributeTypeOC' SUP top STRUCTURAL "
                 + "MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addDITContentRule(
-            "( testallowatrequiredbydcroc-oid "
-                + "NAME 'testAllowATRequiredByDCR' MUST description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
+        .toSchema();
 
     // @formatter:off
-    Entry e = newEntry(schema,
+    final Entry e = newEntry(schema,
         "dn: cn=test,o=test",
         "objectClass: top",
-        "objectClass: testAllowATRequiredByDCROC",
+        "objectClass: testDisallowedAttributeTypeOC",
         "cn: test",
         "description: foo");
     // @formatter:on
 
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isTrue();
-  }
+    assertDoesNotConformToSchema(e, schema, defaultPolicy());
 
-
-
-  /**
-   * 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(enabled = false)
-  public void testRequireAttributeRequiredByDCR() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testrequireatrequiredbydcroc-oid "
-                + "NAME 'testRequireATRequiredByDCROC' SUP top STRUCTURAL "
-                + "MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addDITContentRule(
-            "( testrequireatrequiredbydcroc-oid "
-                + "NAME 'testRequireATRequiredByDCR' MUST description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: testRequireATRequiredByDCROC",
-        "cn: test");
-    // @formatter:on
-
-    failOnlyForStrictEvaluation(e, schema);
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testDontRequireAttributeRequiredByObsoleteDCR() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testdontrequireatrequiredbyobsoletedcroc-oid "
-                + "NAME 'testDontRequireATRequiredByObsoleteDCROC' SUP top "
-                + "STRUCTURAL MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')",
-            false)
-        .addDITContentRule(
-            "( testdontrequireatrequiredbyobsoletedcroc-oid "
-                + "NAME 'testDontRequireATRequiredByObsoleteDCR' OBSOLETE "
-                + "MUST description X-ORIGIN 'EntrySchemaCheckingTestCase' )",
-            false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: testDontRequireATRequiredByObsoleteDCROC",
-        "cn: test");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isTrue();
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testAllowAttributeAllowedByDCR() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testallowatallowedbydcroc-oid "
-                + "NAME 'testAllowATAllowedByDCROC' SUP top STRUCTURAL "
-                + "MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addDITContentRule(
-            "( testallowatallowedbydcroc-oid "
-                + "NAME 'testAllowATAllowedByDCR' MAY description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: testAllowATAllowedByDCROC",
-        "cn: test",
-        "description: foo");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isTrue();
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testDontRequireAttributeAllowedByDCR() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testdontrequireatallowedbydcroc-oid "
-                + "NAME 'testDontRequireATAllowedByDCROC' SUP top STRUCTURAL "
-                + "MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addDITContentRule(
-            "( testdontrequireatallowedbydcroc-oid "
-                + "NAME 'testDontRequireATAllowedByDCR' MAY description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: testDontRequireATAllowedByDCROC",
-        "cn: test");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isTrue();
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testDontAllowAttributeProhibitedByDCR() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testdontallowattributeprohibitedbydcroc-oid "
-                + "NAME 'testDontAllowAttributeProhibitedByDCROC' SUP top "
-                + "STRUCTURAL MUST cn MAY description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addDITContentRule(
-            "( testdontallowattributeprohibitedbydcroc-oid "
-                + "NAME 'testDontAllowAttributeProhibitedByDCR' NOT description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: testDontAllowAttributeProhibitedByDCROC",
-        "cn: test",
-        "description: foo");
-    // @formatter:on
-
-    failOnlyForStrictEvaluation(e, schema);
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testSatisfiesSingleValuedNameForm() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testsatisfiessinglevaluednameformoc-oid "
-                + "NAME 'testSatisfiesSingleValuedNameFormOC' SUP top STRUCTURAL "
-                + "MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addNameForm(
-            "( testsatisfiessinglevaluednameform-oid "
-                + "NAME 'testSatisfiesSingleValuedNameForm' "
-                + "OC testSatisfiesSingleValuedNameFormOC MUST cn "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: testSatisfiesSingleValuedNameFormOC",
-        "cn: test");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isTrue();
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testViolatesSingleValuedNameForm() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testviolatessinglevaluednameformoc-oid "
-                + "NAME 'testViolatesSingleValuedNameFormOC' SUP top STRUCTURAL "
-                + "MUST cn MAY description X-ORIGIN 'EntrySchemaCheckingTestCase')",
-            false)
-        .addNameForm(
-            "( testviolatessinglevaluednameform-oid "
-                + "NAME 'testViolatesSingleValuedNameForm' "
-                + "OC testViolatesSingleValuedNameFormOC MUST cn "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: description=foo,o=test",
-        "objectClass: top",
-        "objectClass: testViolatesSingleValuedNameFormOC",
-        "cn: test",
-        "description: foo");
-    // @formatter:on
-
-    failOnlyForStrictEvaluation(e, schema);
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testMVViolatesSingleValuedNameForm() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testmvviolatessinglevaluednameformoc-oid "
-                + "NAME 'testMVViolatesSingleValuedNameFormOC' SUP top STRUCTURAL "
-                + "MUST cn MAY description X-ORIGIN 'EntrySchemaCheckingTestCase')",
-            false)
-        .addNameForm(
-            "( testmvviolatessinglevaluednameform-oid "
-                + "NAME 'testMVViolatesSingleValuedNameForm' "
-                + "OC testMVViolatesSingleValuedNameFormOC MUST cn "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test+description=foo,o=test",
-        "objectClass: top",
-        "objectClass: testMVViolatesSingleValuedNameFormOC",
-        "cn: test",
-        "description: foo");
-    // @formatter:on
-
-    failOnlyForStrictEvaluation(e, schema);
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testViolatesSingleValuedObsoleteNameForm() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testviolatessinglevaluedobsoletenameformoc-oid "
-                + "NAME 'testViolatesSingleValuedObsoleteNameFormOC' SUP top "
-                + "STRUCTURAL MUST cn MAY description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addNameForm(
-            "( testviolatessinglevaluedobsoletenameform-oid "
-                + "NAME 'testViolatesSingleValuedObsoleteNameForm' OBSOLETE "
-                + "OC testViolatesSingleValuedObsoleteNameFormOC MUST cn "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: description=foo,o=test",
-        "objectClass: top",
-        "objectClass: testViolatesSingleValuedObsoleteNameFormOC",
-        "cn: test",
-        "description: foo");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isTrue();
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testSatisfiesRequiredMultiValuedNameForm() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testsatisfiesrequiredmultivaluednameformoc-oid "
-                + "NAME 'testSatisfiesRequiredMultiValuedNameFormOC' SUP top "
-                + "STRUCTURAL MUST cn MAY description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addNameForm(
-            "( testsatisfiesrequiredmultivaluednameform-oid "
-                + "NAME 'testSatisfiesRequiredMultiValuedNameForm' "
-                + "OC testSatisfiesRequiredMultiValuedNameFormOC "
-                + "MUST ( cn $ description ) "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test+description=foo,o=test",
-        "objectClass: top",
-        "objectClass: testSatisfiesRequiredMultiValuedNameFormOC",
-        "cn: test",
-        "description: foo");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isTrue();
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testViolatesRequiredMultiValuedNameForm() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testviolatesrequiredmultivaluednameformoc-oid "
-                + "NAME 'testViolatesRequiredMultiValuedNameFormOC' SUP top "
-                + "STRUCTURAL MUST cn MAY description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addNameForm(
-            "( testviolatesrequiredmultivaluednameform-oid "
-                + "NAME 'testViolatesRequiredMultiValuedNameForm' "
-                + "OC testViolatesRequiredMultiValuedNameFormOC "
-                + "MUST ( cn $ description ) "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: testViolatesRequiredMultiValuedNameFormOC",
-        "cn: test",
-        "description: foo");
-    // @formatter:on
-
-    failOnlyForStrictEvaluation(e, schema);
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testSVSatisfiesOptionalMultiValuedNameForm() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testsvsatisfiesoptionalmultivaluednameformoc-oid "
-                + "NAME 'testSVSatisfiesOptionalMultiValuedNameFormOC' SUP top "
-                + "STRUCTURAL MUST cn MAY description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addNameForm(
-            "( testsvsatisfiesoptionalmultivaluednameform-oid "
-                + "NAME 'testSVSatisfiesOptionalMultiValuedNameForm' "
-                + "OC testSVSatisfiesOptionalMultiValuedNameFormOC MUST cn "
-                + "MAY description X-ORIGIN 'EntrySchemaCheckingTestCase' )",
-            false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test,o=test",
-        "objectClass: top",
-        "objectClass: testSVSatisfiesOptionalMultiValuedNameFormOC",
-        "cn: test",
-        "description: foo");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isTrue();
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testMVSatisfiesOptionalMultiValuedNameForm() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testmvsatisfiesoptionalmultivaluednameformoc-oid "
-                + "NAME 'testMVSatisfiesOptionalMultiValuedNameFormOC' SUP top "
-                + "STRUCTURAL MUST cn MAY description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addNameForm(
-            "( testmvsatisfiesoptionalmultivaluednameform-oid "
-                + "NAME 'testMVSatisfiesOptionalMultiValuedNameForm' "
-                + "OC testMVSatisfiesOptionalMultiValuedNameFormOC MUST cn "
-                + "MAY description X-ORIGIN 'EntrySchemaCheckingTestCase' )",
-            false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: cn=test+description=foo,o=test",
-        "objectClass: top",
-        "objectClass: testMVSatisfiesOptionalMultiValuedNameFormOC",
-        "cn: test",
-        "description: foo");
-    // @formatter:on
-
-    assertThat(conformsToSchema(e, schema, defaultPolicy(), null)).isTrue();
-  }
-
-
-
-  /**
-   * 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(enabled = false)
-  public void testSVViolatesOptionalMultiValuedNameForm() throws Exception
-  {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
-        .addObjectClass(
-            "( testsvviolatesoptionalmultivaluednameformoc-oid "
-                + "NAME 'testSVViolatesOptionalMultiValuedNameFormOC' SUP top "
-                + "STRUCTURAL MUST cn MAY description "
-                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
-        .addNameForm(
-            "( testsvviolatesoptionalmultivaluednameform-oid "
-                + "NAME 'testSVViolatesOptionalMultiValuedNameForm' "
-                + "OC testSVViolatesOptionalMultiValuedNameFormOC MUST cn "
-                + "MAY description X-ORIGIN 'EntrySchemaCheckingTestCase' )",
-            false).toSchema();
-
-    // @formatter:off
-    Entry e = newEntry(schema,
-        "dn: description=foo,o=test",
-        "objectClass: top",
-        "objectClass: testSVViolatesOptionalMultiValuedNameFormOC",
-        "cn: test",
-        "description: foo");
-    // @formatter:on
-
-    failOnlyForStrictEvaluation(e, schema);
+    e.removeAttribute("description", "foo");
+    assertConformsToSchema(e, schema, defaultPolicy());
   }
 
 
@@ -1083,10 +248,10 @@
    * @throws Exception
    *           If an unexpected problem occurs.
    */
-  @Test(enabled = false)
+  @Test
   public void testDITStructureRuleConstraints() throws Exception
   {
-    Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
         .addObjectClass(
             "( testditstructureruleconstraintssupoc-oid "
                 + "NAME 'testDITStructureRuleConstraintsSupOC' SUP top "
@@ -1122,10 +287,11 @@
         "cn: child");
     // @formatter:on
 
-    failOnlyForStrictEvaluation(e, schema);
+    assertDoesNotConformToSchema(e, schema, defaultPolicy()
+        .checkDITStructureRules(Policy.REJECT, newResolver(null)));
 
     // @formatter:off
-    Entry p = newEntry(schema,
+    final Entry p = newEntry(schema,
         "dn: ou=parent,o=test",
         "changetype: add",
         "objectClass: top",
@@ -1133,12 +299,8 @@
         "ou: parent");
     // @formatter:on
 
-    assertThat(
-        conformsToSchema(
-            e,
-            schema,
-            defaultPolicy().checkDITStructureRules(Policy.REJECT,
-                newResolver(p)), null)).isFalse();
+    assertConformsToSchema(e, schema,
+        defaultPolicy().checkDITStructureRules(Policy.REJECT, newResolver(p)));
 
     // @formatter:off
     e = newEntry(schema,
@@ -1148,47 +310,129 @@
         "cn: not below valid parent");
     // @formatter:on
 
-    assertThat(
-        conformsToSchema(
-            e,
-            schema,
-            defaultPolicy().checkDITStructureRules(Policy.REJECT,
-                newResolver(null)), null)).isFalse();
+    assertDoesNotConformToSchema(e, schema, defaultPolicy()
+        .checkDITStructureRules(Policy.REJECT, newResolver(null)));
 
     // @formatter:off
     e = newEntry(schema,
-        "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");
+        "dn: o=invalid entry below parent covered by DSR,ou=parent,o=test",
+        "objectClass: top",
+        "objectClass: organization",
+        "o: invalid entry below parent covered by DSR");
     // @formatter:on
 
-    assertThat(
-        conformsToSchema(
-            e,
-            schema,
-            defaultPolicy().checkDITStructureRules(Policy.REJECT,
-                newResolver(p)), null)).isFalse();
+    assertDoesNotConformToSchema(e, schema, defaultPolicy()
+        .checkDITStructureRules(Policy.REJECT, newResolver(p)));
   }
 
 
 
-  private EntryResolver newResolver(final Entry e)
+  /**
+   * 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
   {
-    return new EntryResolver()
-    {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testdontallowattributeprohibitedbydcroc-oid "
+                + "NAME 'testDontAllowAttributeProhibitedByDCROC' SUP top "
+                + "STRUCTURAL MUST cn MAY description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .addDITContentRule(
+            "( testdontallowattributeprohibitedbydcroc-oid "
+                + "NAME 'testDontAllowAttributeProhibitedByDCR' NOT description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
 
-      public Entry getEntry(DN dn) throws ErrorResultException
-      {
-        if (e == null)
-        {
-          throw ErrorResultException.newErrorResult(ResultCode.NO_SUCH_OBJECT,
-              "no such entry " + dn.toString());
-        }
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test,o=test",
+        "objectClass: top",
+        "objectClass: testDontAllowAttributeProhibitedByDCROC",
+        "cn: test",
+        "description: foo");
+    // @formatter:on
 
-        assertThat((Object) dn).isEqualTo(e.getName());
-        return e;
-      }
-    };
+    assertDoesNotConformToSchema(e, schema, defaultPolicy());
+
+    e.removeAttribute("description", "foo");
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testdontrequireatallowedbydcroc-oid "
+                + "NAME 'testDontRequireATAllowedByDCROC' SUP top STRUCTURAL "
+                + "MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .addDITContentRule(
+            "( testdontrequireatallowedbydcroc-oid "
+                + "NAME 'testDontRequireATAllowedByDCR' MAY description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test,o=test",
+        "objectClass: top",
+        "objectClass: testDontRequireATAllowedByDCROC",
+        "cn: test");
+    // @formatter:on
+
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testdontrequireatrequiredbyobsoletedcroc-oid "
+                + "NAME 'testDontRequireATRequiredByObsoleteDCROC' SUP top "
+                + "STRUCTURAL MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')",
+            false)
+        .addDITContentRule(
+            "( testdontrequireatrequiredbyobsoletedcroc-oid "
+                + "NAME 'testDontRequireATRequiredByObsoleteDCR' OBSOLETE "
+                + "MUST description X-ORIGIN 'EntrySchemaCheckingTestCase' )",
+            false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test,o=test",
+        "objectClass: top",
+        "objectClass: testDontRequireATRequiredByObsoleteDCROC",
+        "cn: test");
+    // @formatter:on
+
+    assertConformsToSchema(e, schema, defaultPolicy());
   }
 
 
@@ -1200,24 +444,799 @@
    * @throws Exception
    *           If an unexpected problem occurs.
    */
-  @Test()
+  @Test
   public void testInvalidSuperiorAttribute() throws Exception
   {
     // @formatter:off
-    Entry e = newEntry(
+    final Entry e = newEntry(
         "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",
         "name: foo");
     // @formatter:off
 
-    assertThat(conformsToSchema(e, defaultPolicy(), null)).isFalse();
+    assertDoesNotConformToSchema(e, defaultPolicy());
+
+    e.removeAttribute("name", "foo");
+    assertConformsToSchema(e, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testmissingatrequiredbyauxiliaryoc-oid "
+                + "NAME 'testMissingATRequiredByAuxiliaryOC' SUP top AUXILIARY "
+                + "MUST ( cn $ description ) "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test,o=test",
+        "objectClass: top",
+        "objectClass: device",
+        "objectClass: testMissingATRequiredByAuxiliaryOC",
+        "cn: test");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e, schema, defaultPolicy());
+
+    e.addAttribute("description", "xxx");
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testmissingatrequiredbystructuraloc-oid "
+                + "NAME 'testMissingATRequiredByStructuralOC' SUP top STRUCTURAL "
+                + "MUST ( cn $ description ) "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test,o=test",
+        "objectClass: top",
+        "objectClass: testMissingATRequiredByStructuralOC",
+        "cn: test");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e, schema, defaultPolicy());
+
+    e.addAttribute("description", "xxx");
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * Tests schema checking for an entry that contains multiple structural
+   * objectclasses.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test
+  public void testMultipleStructuralClasses() throws Exception
+  {
+    // @formatter:off
+    final Entry e = newEntry(
+        "dn: uid=test.user,o=test",
+        "objectClass: top",
+        "objectClass: person",
+        "objectClass: organization",
+        "o: test",
+        "sn: User",
+        "cn: Test User");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e, defaultPolicy());
+
+    e.removeAttribute("objectClass", "organization");
+    e.removeAttribute("o", "test");
+
+    assertConformsToSchema(e, ignoreAll().checkAttributeValues(Policy.REJECT));
+  }
+
+
+
+  /**
+   * 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
+  {
+    // @formatter:off
+    final Entry e = newEntry(
+        "dn: o=test",
+        "objectClass: top",
+        "objectClass: organization",
+        "o: test",
+        "o: foo");
+    // @formatter:on
+
+    assertConformsToSchema(e, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    // @formatter:off
+    final Entry e = newEntry(
+        "dn: dc=example,dc=com",
+        "objectClass: top",
+        "dc: example",
+        "dc: foo");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e,
+        ignoreAll().checkAttributeValues(Policy.REJECT));
+
+    e.removeAttribute("dc", "foo");
+    assertConformsToSchema(e, ignoreAll().checkAttributeValues(Policy.REJECT));
+  }
+
+
+
+  /**
+   * 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
+  {
+    // @formatter:off
+    final Entry e = newEntry(
+        "dn: dc=example,dc=com",
+        "objectClass: top",
+        "objectClass: domain",
+        "dc: example",
+        "creatorsName: cn=Directory Manager",
+        "creatorsName: cn=Another Manager");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e,
+        ignoreAll().checkAttributeValues(Policy.REJECT));
+
+    e.removeAttribute("creatorsName", "cn=Another Manager");
+    assertConformsToSchema(e, ignoreAll().checkAttributeValues(Policy.REJECT));
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testmvsatisfiesoptionalmultivaluednameformoc-oid "
+                + "NAME 'testMVSatisfiesOptionalMultiValuedNameFormOC' SUP top "
+                + "STRUCTURAL MUST cn MAY description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .addNameForm(
+            "( testmvsatisfiesoptionalmultivaluednameform-oid "
+                + "NAME 'testMVSatisfiesOptionalMultiValuedNameForm' "
+                + "OC testMVSatisfiesOptionalMultiValuedNameFormOC MUST cn "
+                + "MAY description X-ORIGIN 'EntrySchemaCheckingTestCase' )",
+            false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test+description=foo,o=test",
+        "objectClass: top",
+        "objectClass: testMVSatisfiesOptionalMultiValuedNameFormOC",
+        "cn: test",
+        "description: foo");
+    // @formatter:on
+
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testmvviolatessinglevaluednameformoc-oid "
+                + "NAME 'testMVViolatesSingleValuedNameFormOC' SUP top STRUCTURAL "
+                + "MUST cn MAY description X-ORIGIN 'EntrySchemaCheckingTestCase')",
+            false)
+        .addNameForm(
+            "( testmvviolatessinglevaluednameform-oid "
+                + "NAME 'testMVViolatesSingleValuedNameForm' "
+                + "OC testMVViolatesSingleValuedNameFormOC MUST cn "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test+description=foo,o=test",
+        "objectClass: top",
+        "objectClass: testMVViolatesSingleValuedNameFormOC",
+        "cn: test",
+        "description: foo");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e, schema, defaultPolicy());
+
+    e.setName("cn=test,o=test");
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( domain-oid " + "NAME 'domain' SUP top STRUCTURAL "
+                + "MUST dc X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: dc=example,dc=com",
+        "objectClass: top",
+        "objectClass: dcObject",
+        "dc: example");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e, schema, defaultPolicy());
+
+    e.addAttribute("objectClass", "domain");
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testrequireatrequiredbydcroc-oid "
+                + "NAME 'testRequireATRequiredByDCROC' SUP top STRUCTURAL "
+                + "MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .addDITContentRule(
+            "( testrequireatrequiredbydcroc-oid "
+                + "NAME 'testRequireATRequiredByDCR' MUST description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test,o=test",
+        "objectClass: top",
+        "objectClass: testRequireATRequiredByDCROC",
+        "cn: test");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e, schema, defaultPolicy());
+
+    e.addAttribute("description", "foo");
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testsatisfiesrequiredmultivaluednameformoc-oid "
+                + "NAME 'testSatisfiesRequiredMultiValuedNameFormOC' SUP top "
+                + "STRUCTURAL MUST cn MAY description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .addNameForm(
+            "( testsatisfiesrequiredmultivaluednameform-oid "
+                + "NAME 'testSatisfiesRequiredMultiValuedNameForm' "
+                + "OC testSatisfiesRequiredMultiValuedNameFormOC "
+                + "MUST ( cn $ description ) "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test+description=foo,o=test",
+        "objectClass: top",
+        "objectClass: testSatisfiesRequiredMultiValuedNameFormOC",
+        "cn: test",
+        "description: foo");
+    // @formatter:on
+
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testsatisfiessinglevaluednameformoc-oid "
+                + "NAME 'testSatisfiesSingleValuedNameFormOC' SUP top STRUCTURAL "
+                + "MUST cn X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .addNameForm(
+            "( testsatisfiessinglevaluednameform-oid "
+                + "NAME 'testSatisfiesSingleValuedNameForm' "
+                + "OC testSatisfiesSingleValuedNameFormOC MUST cn "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test,o=test",
+        "objectClass: top",
+        "objectClass: testSatisfiesSingleValuedNameFormOC",
+        "cn: test");
+    // @formatter:on
+
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testsvsatisfiesoptionalmultivaluednameformoc-oid "
+                + "NAME 'testSVSatisfiesOptionalMultiValuedNameFormOC' SUP top "
+                + "STRUCTURAL MUST cn MAY description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .addNameForm(
+            "( testsvsatisfiesoptionalmultivaluednameform-oid "
+                + "NAME 'testSVSatisfiesOptionalMultiValuedNameForm' "
+                + "OC testSVSatisfiesOptionalMultiValuedNameFormOC MUST cn "
+                + "MAY description X-ORIGIN 'EntrySchemaCheckingTestCase' )",
+            false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test,o=test",
+        "objectClass: top",
+        "objectClass: testSVSatisfiesOptionalMultiValuedNameFormOC",
+        "cn: test",
+        "description: foo");
+    // @formatter:on
+
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testsvviolatesoptionalmultivaluednameformoc-oid "
+                + "NAME 'testSVViolatesOptionalMultiValuedNameFormOC' SUP top "
+                + "STRUCTURAL MUST cn MAY description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .addNameForm(
+            "( testsvviolatesoptionalmultivaluednameform-oid "
+                + "NAME 'testSVViolatesOptionalMultiValuedNameForm' "
+                + "OC testSVViolatesOptionalMultiValuedNameFormOC MUST cn "
+                + "MAY description X-ORIGIN 'EntrySchemaCheckingTestCase' )",
+            false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: description=foo,o=test",
+        "objectClass: top",
+        "objectClass: testSVViolatesOptionalMultiValuedNameFormOC",
+        "cn: test",
+        "description: foo");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e, schema, defaultPolicy());
+
+    e.setName("cn=test+description=foo,o=test");
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    // @formatter:off
+    final Entry e = newEntry(
+        "dn: cn=test,o=test",
+        "objectClass: top",
+        "objectClass: person",
+        "objectClass: xxxundefinedauxiliaryxxx",
+        "cn: test",
+        "sn: test");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e, defaultPolicy());
+
+    e.removeAttribute("objectClass", "xxxundefinedauxiliaryxxx");
+    assertConformsToSchema(e, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    // @formatter:off
+    final Entry e = newEntry(
+        "dn: cn=test,o=test",
+        "objectClass: top",
+        "objectClass: xxxundefinedstructuralxxx",
+        "o: test");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e, defaultPolicy());
+
+    e.removeAttribute("objectClass", "xxxundefinedstructuralxxx");
+    e.addAttribute("objectClass", "organization");
+    assertConformsToSchema(e, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    // @formatter:off
+    final Entry e = newEntry(
+        "dn: dc=example,dc=com",
+        "objectClass: top",
+        "objectClass: organization",
+        "o: example");
+    // @formatter:on
+
+    assertConformsToSchema(e, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    // @formatter:off
+    final Entry e = newEntry(
+        "dn: dc=example,dc=com",
+        "objectClass: top",
+        "objectClass: organization",
+        "objectClass: dcObject",
+        "dc: example",
+        "o: Example Org");
+    // @formatter:on
+
+    assertConformsToSchema(e, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testviolatesrequiredmultivaluednameformoc-oid "
+                + "NAME 'testViolatesRequiredMultiValuedNameFormOC' SUP top "
+                + "STRUCTURAL MUST cn MAY description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .addNameForm(
+            "( testviolatesrequiredmultivaluednameform-oid "
+                + "NAME 'testViolatesRequiredMultiValuedNameForm' "
+                + "OC testViolatesRequiredMultiValuedNameFormOC "
+                + "MUST ( cn $ description ) "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: cn=test,o=test",
+        "objectClass: top",
+        "objectClass: testViolatesRequiredMultiValuedNameFormOC",
+        "cn: test",
+        "description: foo");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e, schema, defaultPolicy());
+
+    e.setName("cn=test+description=foo,o=test");
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testviolatessinglevaluednameformoc-oid "
+                + "NAME 'testViolatesSingleValuedNameFormOC' SUP top STRUCTURAL "
+                + "MUST cn MAY description X-ORIGIN 'EntrySchemaCheckingTestCase')",
+            false)
+        .addNameForm(
+            "( testviolatessinglevaluednameform-oid "
+                + "NAME 'testViolatesSingleValuedNameForm' "
+                + "OC testViolatesSingleValuedNameFormOC MUST cn "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: description=foo,o=test",
+        "objectClass: top",
+        "objectClass: testViolatesSingleValuedNameFormOC",
+        "cn: test",
+        "description: foo");
+    // @formatter:on
+
+    assertDoesNotConformToSchema(e, schema, defaultPolicy());
+
+    e.setName("cn=test,o=test");
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  /**
+   * 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
+  {
+    final Schema schema = new SchemaBuilder(Schema.getDefaultSchema())
+        .addObjectClass(
+            "( testviolatessinglevaluedobsoletenameformoc-oid "
+                + "NAME 'testViolatesSingleValuedObsoleteNameFormOC' SUP top "
+                + "STRUCTURAL MUST cn MAY description "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase')", false)
+        .addNameForm(
+            "( testviolatessinglevaluedobsoletenameform-oid "
+                + "NAME 'testViolatesSingleValuedObsoleteNameForm' OBSOLETE "
+                + "OC testViolatesSingleValuedObsoleteNameFormOC MUST cn "
+                + "X-ORIGIN 'EntrySchemaCheckingTestCase' )", false).toSchema();
+
+    // @formatter:off
+    final Entry e = newEntry(schema,
+        "dn: description=foo,o=test",
+        "objectClass: top",
+        "objectClass: testViolatesSingleValuedObsoleteNameFormOC",
+        "cn: test",
+        "description: foo");
+    // @formatter:on
+
+    assertConformsToSchema(e, schema, defaultPolicy());
+  }
+
+
+
+  private void assertConformsToSchema(final Entry entry, final Schema schema,
+      final SchemaValidationPolicy policy)
+  {
+    final List<LocalizableMessage> errorMessages = new LinkedList<LocalizableMessage>();
+    assertThat(schema.validateEntry(entry, policy, errorMessages)).as(
+        errorMessages.toString()).isTrue();
+  }
+
+
+
+  private void assertConformsToSchema(final Entry entry,
+      final SchemaValidationPolicy policy)
+  {
+    assertConformsToSchema(entry, Schema.getDefaultSchema(), policy);
+  }
+
+
+
+  private void assertDoesNotConformToSchema(final Entry entry,
+      final Schema schema, final SchemaValidationPolicy policy)
+  {
+    final List<LocalizableMessage> errorMessages = new LinkedList<LocalizableMessage>();
+    assertThat(schema.validateEntry(entry, policy, errorMessages)).as(
+        errorMessages.toString()).isFalse();
+  }
+
+
+
+  private void assertDoesNotConformToSchema(final Entry entry,
+      final SchemaValidationPolicy policy)
+  {
+    assertDoesNotConformToSchema(entry, Schema.getDefaultSchema(), policy);
+  }
+
+
+
+  private Entry newEntry(final Schema schema, final String... ldif)
+  {
+    try
+    {
+      return new LDIFEntryReader(ldif).setSchema(schema).readEntry();
+    }
+    catch (final Exception e)
+    {
+      throw new IllegalArgumentException(e);
+    }
+  }
+
+
+
+  private Entry newEntry(final String... ldif)
+  {
+    return newEntry(Schema.getDefaultSchema(), ldif);
+  }
+
+
+
+  private EntryResolver newResolver(final Entry e)
+  {
+    return new EntryResolver()
+    {
+
+      public Entry getEntry(final DN dn) throws ErrorResultException
+      {
+        if (e == null)
+        {
+          throw ErrorResultException.newErrorResult(ResultCode.NO_SUCH_OBJECT,
+              "no such entry " + dn.toString());
+        }
+
+        assertThat((Object) dn).isEqualTo(e.getName());
+        return e;
+      }
+    };
   }
 }

--
Gitblit v1.10.0