mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Nicolas Capponi
17.07.2013 7e51919e7cab2dec4f2b18e4b93004f6b3c1ee11
Checkpoint commit for OPENDJ-1235 : Migrate configuration framework

* Migrate all tests from org.opends.server.admin.client.ldap package
** Remove server start from all tests

* Fixes in LDAPManagedObject and LDAPNameBuilder classes :
wrong code conversion from javax.naming classes to SDK DN/RDN classes



7 files added
2 files modified
2060 ■■■■■ changed files
opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java 7 ●●●● patch | view | raw | blame | history
opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPNameBuilder.java 36 ●●●●● patch | view | raw | blame | history
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/AggregationClientTest.java 314 ●●●●● patch | view | raw | blame | history
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/CreateEntryMockLDAPConnection.java 112 ●●●●● patch | view | raw | blame | history
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/DeleteSubtreeMockLDAPConnection.java 70 ●●●●● patch | view | raw | blame | history
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/LDAPClientTest.java 889 ●●●●● patch | view | raw | blame | history
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockConstraint.java 131 ●●●●● patch | view | raw | blame | history
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockLDAPConnection.java 386 ●●●●● patch | view | raw | blame | history
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/ModifyEntryMockLDAPConnection.java 115 ●●●●● patch | view | raw | blame | history
opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java
@@ -37,7 +37,6 @@
import org.forgerock.opendj.ldap.LinkedAttribute;
import org.forgerock.opendj.ldap.LinkedHashMapEntry;
import org.forgerock.opendj.ldap.ModificationType;
import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.requests.ModifyRequest;
import org.forgerock.opendj.ldap.requests.Requests;
@@ -175,8 +174,7 @@
                addObjectClassesToEntry(objectClasses, entry);
                // Create the branch's naming attribute.
                RDN rdn = dn.parent(dn.size() - 1).rdn();
                entry.addAttribute(rdn.getFirstAVA().toAttribute());
                entry.addAttribute(dn.rdn().getFirstAVA().toAttribute());
                // Create the entry.
                try {
@@ -204,8 +202,7 @@
        // Create the naming attribute if there is not naming property.
        PropertyDefinition<?> namingPropertyDef = getNamingPropertyDefinition();
        if (namingPropertyDef == null) {
            RDN rdn = dn.parent(dn.size() - 1).rdn();
            entry.addAttribute(rdn.getFirstAVA().toAttribute());
            entry.addAttribute(dn.rdn().getFirstAVA().toAttribute());
        }
        // Create the remaining attributes.
opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPNameBuilder.java
@@ -26,8 +26,10 @@
package org.opends.server.admin.client.ldap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.RDN;
@@ -104,10 +106,9 @@
        return builder.getInstance();
    }
    // The list of RDNs in big-endian order.
    /** The list of RDNs in big-endian order. */
    private final LinkedList<RDN> rdns;
    // The LDAP profile.
    private final LDAPProfile profile;
    /**
@@ -145,9 +146,24 @@
    public void appendManagedObjectPathElement(RelationDefinition<?, ?> r) {
        // Add the RDN sequence representing the relation.
        DN dn = DN.valueOf(profile.getRelationRDNSequence(r));
        List<RDN> rdnsOfDn = getRdnsInBigEndianOrder(dn);
        rdns.addAll(rdnsOfDn);
    }
    /**
     * Returns list of RDNs of provided DN in big-endian order.
     *
     * @param dn
     *            The DN to decompose in RDNs.
     * @return rdns in big endian order
     */
    private List<RDN> getRdnsInBigEndianOrder(DN dn) {
        List<RDN> rdnsOfDn = new ArrayList<RDN>();
        for (RDN rdn : dn) {
            rdns.add(rdn);
            rdnsOfDn.add(rdn);
        }
        Collections.reverse(rdnsOfDn);
        return rdnsOfDn;
    }
    /**
@@ -188,16 +204,10 @@
     * @return Returns the new DN instance.
     */
    public DN getInstance() {
        if (rdns.isEmpty()) {
            return DN.rootDN();
        DN dn = DN.rootDN();
        for (RDN rdn : rdns) {
            dn = dn.child(rdn);
        }
        else {
            Collections.reverse(rdns);
            DN dn = DN.valueOf(rdns.removeFirst().toString());
            for (RDN rdn : rdns) {
                dn = dn.child(rdn);
            }
            return dn;
        }
        return dn;
    }
}
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/AggregationClientTest.java
New file
@@ -0,0 +1,314 @@
/*
 * 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 2007-2008 Sun Microsystems, Inc.
 */
package org.opends.server.admin.client.ldap;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;
import org.forgerock.opendj.admin.client.RootCfgClient;
import org.opends.server.admin.AdminTestCase;
import org.opends.server.admin.IllegalPropertyValueStringException;
import org.opends.server.admin.PropertyException;
import org.opends.server.admin.TestCfg;
import org.opends.server.admin.TestChildCfgClient;
import org.opends.server.admin.TestChildCfgDefn;
import org.opends.server.admin.TestParentCfgClient;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.core.DirectoryServer;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@SuppressWarnings("javadoc")
@Test(singleThreaded = true)
public class AggregationClientTest extends AdminTestCase {
    // Test LDIF.
    private static final String[] TEST_LDIF = new String[] {
            // Base entries.
            "dn: cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-branch",
            "cn: config",
            "",
            "dn: cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-branch",
            "cn: test-parents",
            "",
            // Parent 1 - uses default values for
            // optional-multi-valued-dn-property.
            "dn: cn=test parent 1,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-test-parent-dummy",
            "cn: test parent 1",
            "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description",
            "",
            // Child base entry.
            "dn:cn=test children,cn=test parent 1,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-branch",
            "cn: multiple children",
            "",
            // Child 1 has no references.
            "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-test-child-dummy",
            "cn: test child 1",
            "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description",
            "",
            // Child 2 has a single valid reference.
            "dn: cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-test-child-dummy",
            "cn: test child 2",
            "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description",
            "ds-cfg-rotation-policy: cn=LDAP Connection Handler, cn=connection handlers, cn=config",
            "",
            // Child 3 has a multiple valid references.
            "dn: cn=test child 3,cn=test children,cn=test parent 1,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-test-child-dummy",
            "cn: test child 3",
            "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description",
            "ds-cfg-rotation-policy: cn=LDAP Connection Handler, cn=connection handlers, cn=config",
            "ds-cfg-rotation-policy: cn=LDAPS Connection Handler, cn=connection handlers, cn=config",
            "",
            // Child 4 has a single bad reference.
            "dn: cn=test child 4,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top",
            "objectclass: ds-cfg-test-child-dummy", "cn: test child 4", "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description",
            "ds-cfg-rotation-policy: cn=LDAP Connection Handler, cn=bad rdn, cn=config", "",
            "dn: cn=Connection Handlers,cn=config", "objectClass: top", "objectClass: ds-cfg-branch",
            "cn: Connection Handlers", "", "dn: cn=LDAP Connection Handler,cn=Connection Handlers,cn=config",
            "objectClass: top", "objectClass: ds-cfg-connection-handler",
            "objectClass: ds-cfg-ldap-connection-handler", "cn: LDAP Connection Handler",
            "ds-cfg-java-class: org.opends.server.protocols.ldap.LDAPConnectionHandler", "ds-cfg-enabled: true",
            "ds-cfg-listen-address: 0.0.0.0", "ds-cfg-listen-port: 389", "",
            "dn: cn=LDAPS Connection Handler,cn=Connection Handlers,cn=config", "objectClass: top",
            "objectClass: ds-cfg-connection-handler", "objectClass: ds-cfg-ldap-connection-handler",
            "cn: LDAPS Connection Handler",
            "ds-cfg-java-class: org.opends.server.protocols.ldap.LDAPConnectionHandler", "ds-cfg-enabled: false",
            "ds-cfg-listen-address: 0.0.0.0", "ds-cfg-listen-port: 636", "ds-cfg-use-ssl: true",
            "ds-cfg-ssl-client-auth-policy: optional", "ds-cfg-ssl-cert-nickname: server-cert",
            "ds-cfg-key-manager-provider: cn=JKS,cn=Key Manager Providers,cn=config",
            "ds-cfg-trust-manager-provider: cn=JKS,cn=Trust Manager Providers,cn=config", "",
            "dn: cn=JMX Connection Handler,cn=Connection Handlers,cn=config", "objectClass: top",
            "objectClass: ds-cfg-connection-handler", "objectClass: ds-cfg-jmx-connection-handler",
            "cn: JMX Connection Handler", "ds-cfg-java-class: org.opends.server.protocols.jmx.JmxConnectionHandler",
            "ds-cfg-enabled: false", "ds-cfg-listen-port: 1689", "" };
    @BeforeClass
    public void setUp() throws Exception {
        disableClassValidationForProperties();
        TestCfg.setUp();
    }
    /**
     * Tears down test environment.
     */
    @AfterClass
    public void tearDown() {
        TestCfg.cleanup();
    }
    /**
     * Tests that aggregation contains no values when it contains does not
     * contain any DN attribute values.
     *
     * @throws Exception
     *             If the test unexpectedly fails.
     */
    @Test
    public void testAggregationEmpty() throws Exception {
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        TestChildCfgClient child = parent.getTestChild("test child 1");
        assertSetEquals(child.getAggregationProperty(), new String[0]);
    }
    /**
     * Tests that aggregation contains single valid value when it contains a
     * single valid DN attribute values.
     *
     * @throws Exception
     *             If the test unexpectedly fails.
     */
    @Test
    public void testAggregationSingle() throws Exception {
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        TestChildCfgClient child = parent.getTestChild("test child 2");
        // Test normalization.
        assertSetEquals(child.getAggregationProperty(), "LDAP Connection Handler");
        assertSetEquals(child.getAggregationProperty(), "  LDAP   Connection  Handler ");
        assertSetEquals(child.getAggregationProperty(), "  ldap connection HANDLER ");
    }
    /**
     * Tests that aggregation contains multiple valid values when it contains a
     * multiple valid DN attribute values.
     *
     * @throws Exception
     *             If the test unexpectedly fails.
     */
    @Test
    public void testAggregationMultiple() throws Exception {
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        TestChildCfgClient child = parent.getTestChild("test child 3");
        assertSetEquals(child.getAggregationProperty(), "LDAPS Connection Handler", "LDAP Connection Handler");
    }
    /**
     * Tests that aggregation is rejected when the LDAP DN contains a valid RDN
     * but an invalid parent DN.
     *
     * @throws Exception
     *             If the test unexpectedly fails.
     */
    @Test
    public void testAggregationBadBaseDN() throws Exception {
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        try {
            parent.getTestChild("test child 4");
            Assert.fail("Unexpectedly retrieved test child 4" + " when it had a bad aggregation value");
        } catch (ManagedObjectDecodingException e) {
            Collection<PropertyException> causes = e.getCauses();
            Assert.assertEquals(causes.size(), 1);
            Throwable cause = causes.iterator().next();
            if (cause instanceof IllegalPropertyValueStringException) {
                IllegalPropertyValueStringException pe = (IllegalPropertyValueStringException) cause;
                Assert.assertEquals(pe.getPropertyDefinition(), TestChildCfgDefn.getInstance()
                        .getAggregationPropertyPropertyDefinition());
                Assert.assertEquals(pe.getIllegalValueString(), "cn=LDAP Connection Handler, cn=bad rdn, cn=config");
            } else {
                // Got an unexpected cause.
                throw e;
            }
        }
    }
    /**
     * Tests creation of a child managed object with a single reference.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testCreateChildManagedObject() throws Exception {
        CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
                "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
        c.importLDIF(TEST_LDIF);
        c.addExpectedAttribute("cn", "test child new");
        c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
        c.addExpectedAttribute("ds-cfg-enabled", "true");
        c.addExpectedAttribute("ds-cfg-java-class",
                "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
        c.addExpectedAttribute("ds-cfg-attribute-type", "description");
        c.addExpectedAttribute("ds-cfg-rotation-policy",
                "cn=LDAP Connection Handler,cn=connection handlers, cn=config");
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
        child.setMandatoryBooleanProperty(true);
        child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
        child.setAggregationProperty(Collections.singleton("LDAP Connection Handler"));
        child.commit();
        c.assertEntryIsCreated();
    }
    /**
     * Tests modification of a child managed object so that it has a different
     * reference.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testModifyChildManagedObject() throws Exception {
        ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
                "cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config");
        c.importLDIF(TEST_LDIF);
        c.addExpectedModification("ds-cfg-rotation-policy",
                "cn=LDAPS Connection Handler,cn=connection handlers, cn=config",
                "cn=JMX Connection Handler,cn=connection handlers, cn=config");
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        TestChildCfgClient child = parent.getTestChild("test child 2");
        child.setAggregationProperty(Arrays.asList("LDAPS Connection Handler", "JMX Connection Handler"));
        child.commit();
        Assert.assertTrue(c.isEntryModified());
    }
    // Retrieve the named test parent managed object.
    private TestParentCfgClient getTestParent(ManagementContext context, String name) throws Exception {
        ManagedObject<RootCfgClient> root = context.getRootConfigurationManagedObject();
        return root.getChild(TestCfg.getTestOneToManyParentRelationDefinition(), name).getConfiguration();
    }
    // Asserts that the actual set of DNs contains the expected values.
    private void assertSetEquals(SortedSet<String> actual, String... expected) {
        SortedSet<String> values = new TreeSet<String>(TestChildCfgDefn.getInstance()
                .getAggregationPropertyPropertyDefinition());
        if (expected != null) {
            for (String value : expected) {
                values.add(value);
            }
        }
        Assert.assertEquals((Object) actual, (Object) values);
    }
}
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/CreateEntryMockLDAPConnection.java
New file
@@ -0,0 +1,112 @@
/*
 * 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.
 */
package org.opends.server.admin.client.ldap;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.testng.Assert;
import com.forgerock.opendj.util.Validator;
/**
 * A mock LDAP connection which is used to verify that an add operation was
 * requested and that it has the correct parameters.
 */
public final class CreateEntryMockLDAPConnection extends MockLDAPConnection {
    // Detect multiple calls.
    private boolean alreadyAdded = false;
    // The expected set of attributes (attribute name -> list of
    // values).
    private final Map<String, List<String>> attributes = new HashMap<String, List<String>>();
    // The expected DN.
    private final DN expectedDN;
    /**
     * Create a new mock ldap connection for detecting add operations.
     *
     * @param dn
     *            The expected DN of the entry to be added.
     */
    public CreateEntryMockLDAPConnection(String dn) {
        this.expectedDN = DN.valueOf(dn);
    }
    /**
     * Add an attribute which should be part of the add operation.
     *
     * @param expectedName
     *            The name of the expected attribute.
     * @param expectedValues
     *            The attribute's expected values (never empty).
     */
    public void addExpectedAttribute(String expectedName, String... expectedValues) {
        Validator.ensureNotNull(expectedName);
        Validator.ensureNotNull(expectedValues);
        Validator.ensureTrue(expectedValues.length > 0, "should have at least one expected value");
        attributes.put(expectedName, Arrays.asList(expectedValues));
    }
    /**
     * Asserts that the entry was created.
     */
    public void assertEntryIsCreated() {
        Assert.assertTrue(alreadyAdded);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void createEntry(Entry entry) throws ErrorResultException {
        Assert.assertFalse(alreadyAdded);
        Assert.assertEquals(entry.getName(), expectedDN);
        Map<String, List<String>> expected = new HashMap<String, List<String>>(this.attributes);
        for (Attribute attribute : entry.getAllAttributes()) {
            String attrName = attribute.getAttributeDescription().getAttributeType().getNameOrOID();
            List<String> values = expected.remove(attrName);
            if (values == null) {
                Assert.fail("Unexpected attribute " + attrName);
            }
            assertAttributeEquals(attribute, values);
        }
        if (!expected.isEmpty()) {
            Assert.fail("Missing expected attributes: " + expected.keySet());
        }
        alreadyAdded = true;
    }
}
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/DeleteSubtreeMockLDAPConnection.java
New file
@@ -0,0 +1,70 @@
/*
 * 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.
 */
package org.opends.server.admin.client.ldap;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.testng.Assert;
/**
 * A mock LDAP connection which is used to verify that a delete subtree takes
 * place.
 */
public final class DeleteSubtreeMockLDAPConnection extends MockLDAPConnection {
    // Detect multiple calls.
    private boolean alreadyDeleted = false;
    // The expected DN.
    private final DN expectedDN;
    /**
     * Create a new mock ldap connection for detecting subtree deletes.
     *
     * @param dn
     *            The expected subtree DN.
     */
    public DeleteSubtreeMockLDAPConnection(String dn) {
        this.expectedDN = DN.valueOf(dn);
    }
    /**
     * Asserts that the subtree was deleted.
     */
    public void assertSubtreeIsDeleted() {
        Assert.assertTrue(alreadyDeleted);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void deleteSubtree(DN dn) throws ErrorResultException {
        Assert.assertFalse(alreadyDeleted);
        Assert.assertEquals(dn, expectedDN);
        alreadyDeleted = true;
    }
}
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/LDAPClientTest.java
New file
@@ -0,0 +1,889 @@
/*
 * 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.
 */
package org.opends.server.admin.client.ldap;
import static org.fest.assertions.Assertions.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.SortedSet;
import org.forgerock.opendj.admin.client.RootCfgClient;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.opends.server.admin.AdminTestCase;
import org.opends.server.admin.Constraint;
import org.opends.server.admin.ManagedObjectAlreadyExistsException;
import org.opends.server.admin.ManagedObjectNotFoundException;
import org.opends.server.admin.TestCfg;
import org.opends.server.admin.TestChildCfgClient;
import org.opends.server.admin.TestChildCfgDefn;
import org.opends.server.admin.TestParentCfgClient;
import org.opends.server.admin.TestParentCfgDefn;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.core.DirectoryServer;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@SuppressWarnings("javadoc")
@Test(singleThreaded = true)
public final class LDAPClientTest extends AdminTestCase {
    // Test LDIF.
    private static final String[] TEST_LDIF = new String[] {
            // Base entries.
            "dn: cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-branch",
            "cn: config",
            "",
            "dn: cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-branch",
            "cn: test-parents",
            "",
            // Parent 1 - uses default values for
            // optional-multi-valued-dn-property.
            "dn: cn=test parent 1,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-test-parent-dummy",
            "cn: test parent 1",
            "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description",
            "",
            // Parent 2 - overrides default values for
            // optional-multi-valued-dn-property.
            "dn: cn=test parent 2,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-test-parent-dummy",
            "cn: test parent 2",
            "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description",
            "ds-cfg-base-dn: dc=default value p2v1,dc=com",
            "ds-cfg-base-dn: dc=default value p2v2,dc=com",
            "",
            // Parent 3 - overrides default values for
            // optional-multi-valued-dn-property.
            "dn: cn=test parent 3,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-test-parent-dummy",
            "cn: test parent 3",
            "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description",
            "ds-cfg-base-dn: dc=default value p3v1,dc=com",
            "ds-cfg-base-dn: dc=default value p3v2,dc=com",
            "",
            // Child base entries.
            "dn:cn=test children,cn=test parent 1,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-branch",
            "cn: multiple children",
            "",
            "dn:cn=test children,cn=test parent 2,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-branch",
            "cn: multiple children",
            "",
            // Child 1 inherits defaults for both
            // optional-multi-valued-dn-property1 and
            // optional-multi-valued-dn-property2.
            "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-test-child-dummy",
            "cn: test child 1",
            "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description",
            "",
            // Child 2 inherits defaults for
            // optional-multi-valued-dn-property2.
            "dn: cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-test-child-dummy",
            "cn: test child 2",
            "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description",
            "ds-cfg-base-dn: dc=default value c2v1,dc=com",
            "ds-cfg-base-dn: dc=default value c2v2,dc=com",
            "",
            // Child 3 overrides defaults for
            // optional-multi-valued-dn-property1 and
            // optional-multi-valued-dn-property2.
            "dn: cn=test child 3,cn=test children,cn=test parent 1,cn=test parents,cn=config",
            "objectclass: top",
            "objectclass: ds-cfg-test-child-dummy",
            "cn: test child 3",
            "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description",
            "ds-cfg-base-dn: dc=default value c3v1,dc=com",
            "ds-cfg-base-dn: dc=default value c3v2,dc=com",
            "ds-cfg-group-dn: dc=default value c3v3,dc=com",
            "ds-cfg-group-dn: dc=default value c3v4,dc=com",
            "",
            // Child 4 inherits overridden defaults for both
            // optional-multi-valued-dn-property1 and
            // optional-multi-valued-dn-property2.
            "dn: cn=test child 1,cn=test children,cn=test parent 2,cn=test parents,cn=config", "objectclass: top",
            "objectclass: ds-cfg-test-child-dummy", "cn: test child 1", "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
            "ds-cfg-attribute-type: description", "", };
    /**
     * Provide valid naming exception to client API exception mappings.
     *
     * @return Returns valid naming exception to client API exception mappings.
     */
    @DataProvider(name = "createManagedObjectExceptions")
    public Object[][] createManagedObjectExceptions() {
        return new Object[][] {
            // result code corresponding to exception thrown, expected exception, expected code result
            { ResultCode.PROTOCOL_ERROR, ErrorResultException.class, ResultCode.PROTOCOL_ERROR },
            { ResultCode.UNAVAILABLE , ErrorResultException.class, ResultCode.UNAVAILABLE },
            { ResultCode.ENTRY_ALREADY_EXISTS, ManagedObjectAlreadyExistsException.class, null },
            { ResultCode.INSUFFICIENT_ACCESS_RIGHTS, ErrorResultException.class,
                    ResultCode.INSUFFICIENT_ACCESS_RIGHTS },
            { ResultCode.UNWILLING_TO_PERFORM, OperationRejectedException.class, null }
        };
    }
    /**
     * Provide valid naming exception to client API exception mappings.
     *
     * @return Returns valid naming exception to client API exception mappings.
     */
    @DataProvider(name = "getManagedObjectExceptions")
    public Object[][] getManagedObjectExceptions() {
        return new Object[][] {
            // result code corresponding to exception thrown, expected exception, expected code result
            { ResultCode.PROTOCOL_ERROR, ErrorResultException.class, ResultCode.PROTOCOL_ERROR },
            { ResultCode.UNAVAILABLE, ErrorResultException.class, ResultCode.UNAVAILABLE },
            { ResultCode.NO_SUCH_OBJECT, ManagedObjectNotFoundException.class, null },
            { ResultCode.INSUFFICIENT_ACCESS_RIGHTS, ErrorResultException.class,
                ResultCode.INSUFFICIENT_ACCESS_RIGHTS },
            { ResultCode.UNWILLING_TO_PERFORM, ErrorResultException.class,
                ResultCode.UNWILLING_TO_PERFORM }
        };
    }
    @BeforeClass
    public void setUp() throws Exception {
        disableClassValidationForProperties();
        TestCfg.setUp();
    }
    @AfterClass
    public void tearDown() {
        TestCfg.cleanup();
    }
    /**
     * Tests creation of a child managed object.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testCreateChildManagedObject() throws Exception {
        CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
                "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
        c.importLDIF(TEST_LDIF);
        c.addExpectedAttribute("cn", "test child new");
        c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
        c.addExpectedAttribute("ds-cfg-enabled", "true");
        c.addExpectedAttribute("ds-cfg-java-class",
                "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
        c.addExpectedAttribute("ds-cfg-attribute-type", "description");
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
        child.setMandatoryBooleanProperty(true);
        child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
        child.commit();
        c.assertEntryIsCreated();
    }
    /**
     * Tests creation of a top-level managed object using fails when an
     * underlying exception occurs.
     */
    @Test(dataProvider = "createManagedObjectExceptions")
    public void testCreateManagedObjectException(final ResultCode resultCodeOfThrownException,
            Class<? extends Exception> expectedExceptionClass, ResultCode expectedCode) {
        MockLDAPConnection conn = new MockLDAPConnection() {
            @Override
            public void createEntry(Entry entry) throws ErrorResultException {
                throw ErrorResultException.newErrorResult(resultCodeOfThrownException);
            }
        };
        conn.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(conn);
        try {
            TestParentCfgClient parent = createTestParent(ctx, "test parent new");
            parent.setMandatoryBooleanProperty(true);
            parent.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
            parent.commit();
        } catch (Exception e) {
            if (expectedExceptionClass.equals(ErrorResultException.class)) {
                assertThat(e).isInstanceOf(ErrorResultException.class);
                assertThat(((ErrorResultException) e).getResult().getResultCode()).isEqualTo(expectedCode);
            }
            else {
                assertThat(e).isInstanceOf(expectedExceptionClass);
            }
        }
    }
    /**
     * Tests creation of a top-level managed object.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testCreateTopLevelManagedObject() throws Exception {
        CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
                "cn=test parent new,cn=test parents,cn=config");
        c.importLDIF(TEST_LDIF);
        c.addExpectedAttribute("cn", "test parent new");
        c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-parent-dummy");
        c.addExpectedAttribute("ds-cfg-enabled", "true");
        c.addExpectedAttribute("ds-cfg-java-class",
                "org.opends.server.extensions.SomeVirtualAttributeProvider");
        c.addExpectedAttribute("ds-cfg-attribute-type", "description");
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = createTestParent(ctx, "test parent new");
        parent.setMandatoryBooleanProperty(true);
        parent.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
        parent.commit();
        c.assertEntryIsCreated();
    }
    /**
     * Tests retrieval of a child managed object with non-default values.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testGetChildManagedObject() throws Exception {
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        TestChildCfgClient child = parent.getTestChild("test child 3");
        Assert.assertEquals(child.isMandatoryBooleanProperty(), Boolean.TRUE);
        Assert.assertEquals(child.getMandatoryClassProperty(),
                "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
        Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(),
                DirectoryServer.getAttributeType("description"));
        assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=default value c3v1,dc=com",
                "dc=default value c3v2,dc=com");
        assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=default value c3v3,dc=com",
                "dc=default value c3v4,dc=com");
    }
    /**
     * Tests retrieval of a child managed object with default values.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testGetChildManagedObjectDefault() throws Exception {
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        TestChildCfgClient child = parent.getTestChild("test child 1");
        Assert.assertEquals(child.isMandatoryBooleanProperty(), Boolean.TRUE);
        Assert.assertEquals(child.getMandatoryClassProperty(),
                "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
        Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(),
                DirectoryServer.getAttributeType("description"));
        assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=domain1,dc=com", "dc=domain2,dc=com",
                "dc=domain3,dc=com");
        assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=domain1,dc=com", "dc=domain2,dc=com",
                "dc=domain3,dc=com");
        Assert.assertEquals(child.isMandatoryBooleanProperty(), Boolean.TRUE);
    }
    /**
     * Tests retrieval of a top-level managed object fails when an underlying
     * ErrorResultException occurs.
     *
     * @param cause
     *            The ErrorResultException cause of the failure.
     * @param expected
     *            The expected client API exception class.
     */
    @Test(dataProvider = "getManagedObjectExceptions")
    public void testGetManagedObjectException(final ResultCode resultCodeOfThrownException,
            final Class<? extends Exception> expectedExceptionClass, final ResultCode expectedCode) {
        MockLDAPConnection c = new MockLDAPConnection() {
            @Override
            public SearchResultEntry readEntry(DN dn, Collection<String> attrIds) throws ErrorResultException {
                throw ErrorResultException.newErrorResult(resultCodeOfThrownException);
            }
        };
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        try {
            getTestParent(ctx, "test parent 2");
        } catch (Exception e) {
            if (expectedExceptionClass.equals(ErrorResultException.class)) {
                assertThat(e).isInstanceOf(ErrorResultException.class);
                assertThat(((ErrorResultException) e).getResult().getResultCode()).isEqualTo(expectedCode);
            }
            else {
                assertThat(e).isInstanceOf(expectedExceptionClass);
            }
        }
    }
    /**
     * Tests retrieval of a top-level managed object with non-default values.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testGetTopLevelManagedObject() throws Exception {
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 2");
        Assert.assertEquals(parent.isMandatoryBooleanProperty(), Boolean.TRUE);
        Assert.assertEquals(parent.getMandatoryClassProperty(),
                "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
        Assert.assertEquals(parent.getMandatoryReadOnlyAttributeTypeProperty(),
                DirectoryServer.getAttributeType("description"));
        assertDNSetEquals(parent.getOptionalMultiValuedDNProperty(), "dc=default value p2v1,dc=com",
                "dc=default value p2v2,dc=com");
    }
    /**
     * Tests retrieval of a top-level managed object with default values.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testGetTopLevelManagedObjectDefault() throws Exception {
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        Assert.assertEquals(parent.isMandatoryBooleanProperty(), Boolean.TRUE);
        Assert.assertEquals(parent.getMandatoryClassProperty(),
                "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
        Assert.assertEquals(parent.getMandatoryReadOnlyAttributeTypeProperty(),
                DirectoryServer.getAttributeType("description"));
        assertDNSetEquals(parent.getOptionalMultiValuedDNProperty(), "dc=domain1,dc=com", "dc=domain2,dc=com",
                "dc=domain3,dc=com");
    }
    /**
     * Tests retrieval of relative inherited default values.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testInheritedDefaultValues1() throws Exception {
        CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
                "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
        c.importLDIF(TEST_LDIF);
        c.addExpectedAttribute("cn", "test child new");
        c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
        c.addExpectedAttribute("ds-cfg-enabled", "true");
        c.addExpectedAttribute("ds-cfg-java-class",
                "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
        c.addExpectedAttribute("ds-cfg-attribute-type", "description");
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
        // Check pre-commit values.
        Assert.assertEquals(child.isMandatoryBooleanProperty(), null);
        Assert.assertEquals(child.getMandatoryClassProperty(),
                "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
        Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), null);
        assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=domain1,dc=com", "dc=domain2,dc=com",
                "dc=domain3,dc=com");
        assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=domain1,dc=com", "dc=domain2,dc=com",
                "dc=domain3,dc=com");
        // Check that the default values are not committed.
        child.setMandatoryBooleanProperty(true);
        child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
        child.commit();
        c.assertEntryIsCreated();
    }
    /**
     * Tests retrieval of relative inherited default values.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testInheritedDefaultValues2() throws Exception {
        CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
                "cn=test child new,cn=test children,cn=test parent 2,cn=test parents,cn=config");
        c.importLDIF(TEST_LDIF);
        c.addExpectedAttribute("cn", "test child new");
        c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
        c.addExpectedAttribute("ds-cfg-enabled", "true");
        c.addExpectedAttribute("ds-cfg-java-class",
                "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
        c.addExpectedAttribute("ds-cfg-attribute-type", "description");
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 2");
        TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
        // Check pre-commit values.
        Assert.assertEquals(child.isMandatoryBooleanProperty(), null);
        Assert.assertEquals(child.getMandatoryClassProperty(),
                "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
        Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), null);
        assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=default value p2v1,dc=com",
                "dc=default value p2v2,dc=com");
        assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=default value p2v1,dc=com",
                "dc=default value p2v2,dc=com");
        // Check that the default values are not committed.
        child.setMandatoryBooleanProperty(true);
        child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
        child.commit();
        c.assertEntryIsCreated();
    }
    /**
     * Tests listing of child managed objects.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testListChildManagedObjects() throws Exception {
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        String[] actual = parent.listTestChildren();
        String[] expected = new String[] { "test child 1", "test child 2", "test child 3" };
        Assert.assertEqualsNoOrder(actual, expected);
    }
    /**
     * Tests listing of child managed objects when their are not any.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testListChildManagedObjectsEmpty() throws Exception {
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 3");
        String[] actual = parent.listTestChildren();
        String[] expected = new String[] {};
        Assert.assertEqualsNoOrder(actual, expected);
    }
    /**
     * Tests listing of top level managed objects.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testListTopLevelManagedObjects() throws Exception {
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        String[] actual = listTestParents(ctx);
        String[] expected = new String[] { "test parent 1", "test parent 2", "test parent 3" };
        Assert.assertEqualsNoOrder(actual, expected);
    }
    /**
     * Tests listing of top level managed objects when their are not any.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testListTopLevelManagedObjectsEmpty() throws Exception {
        String[] ldif = {};
        MockLDAPConnection c = new MockLDAPConnection();
        c.importLDIF(ldif);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        String[] actual = listTestParents(ctx);
        String[] expected = new String[] {};
        Assert.assertEqualsNoOrder(actual, expected);
    }
    /**
     * Tests modification of a child managed object.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testModifyChildManagedObjectResetToDefault() throws Exception {
        ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
                "cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config");
        c.importLDIF(TEST_LDIF);
        c.addExpectedModification("ds-cfg-base-dn");
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        TestChildCfgClient child = parent.getTestChild("test child 2");
        child.setOptionalMultiValuedDNProperty1(Collections.<DN> emptySet());
        child.commit();
        Assert.assertTrue(c.isEntryModified());
    }
    /**
     * Tests modification of a top-level managed object.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testModifyTopLevelManagedObjectNoChanges() throws Exception {
        ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
                "cn=test parent 1,cn=test parents,cn=config");
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        parent.commit();
        Assert.assertFalse(c.isEntryModified());
    }
    /**
     * Tests modification of a top-level managed object.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testModifyTopLevelManagedObjectWithChanges() throws Exception {
        ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
                "cn=test parent 1,cn=test parents,cn=config");
        c.importLDIF(TEST_LDIF);
        c.addExpectedModification("ds-cfg-enabled", "false");
        c.addExpectedModification("ds-cfg-base-dn", "dc=mod1,dc=com", "dc=mod2,dc=com");
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        parent.setMandatoryBooleanProperty(false);
        parent.setOptionalMultiValuedDNProperty(Arrays.asList(DN.valueOf("dc=mod1,dc=com"),
                DN.valueOf("dc=mod2,dc=com")));
        parent.commit();
        Assert.assertTrue(c.isEntryModified());
    }
    /**
     * Tests removal of a child managed object.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testRemoveChildManagedObject() throws Exception {
        DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
                "cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config");
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
        parent.removeTestChild("test child 1");
        c.assertSubtreeIsDeleted();
    }
    /**
     * Tests removal of a top-level managed object.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testRemoveTopLevelManagedObject() throws Exception {
        DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
                "cn=test parent 1,cn=test parents,cn=config");
        c.importLDIF(TEST_LDIF);
        ManagementContext ctx = LDAPManagementContext.createFromContext(c);
        removeTestParent(ctx, "test parent 1");
        c.assertSubtreeIsDeleted();
    }
    /**
     * Tests creation of a child managed object succeeds when registered add
     * constraints succeed.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testAddConstraintSuccess() throws Exception {
        Constraint constraint = new MockConstraint(true, false, false);
        TestCfg.addConstraint(constraint);
        try {
            CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
                    "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
            c.importLDIF(TEST_LDIF);
            c.addExpectedAttribute("cn", "test child new");
            c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
            c.addExpectedAttribute("ds-cfg-enabled", "true");
            c.addExpectedAttribute("ds-cfg-java-class",
                    "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
            c.addExpectedAttribute("ds-cfg-attribute-type", "description");
            ManagementContext ctx = LDAPManagementContext.createFromContext(c);
            TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
            TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
            child.setMandatoryBooleanProperty(true);
            child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
            child.commit();
            c.assertEntryIsCreated();
        } finally {
            // Clean up.
            TestCfg.removeConstraint(constraint);
        }
    }
    /**
     * Tests creation of a child managed object fails when registered add
     * constraints fail.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test(expectedExceptions = OperationRejectedException.class)
    public void testAddConstraintFail() throws Exception {
        Constraint constraint = new MockConstraint(false, true, true);
        TestCfg.addConstraint(constraint);
        try {
            CreateEntryMockLDAPConnection conn = new CreateEntryMockLDAPConnection(
                    "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
            conn.importLDIF(TEST_LDIF);
            conn.addExpectedAttribute("cn", "test child new");
            conn.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
            conn.addExpectedAttribute("ds-cfg-enabled", "true");
            conn.addExpectedAttribute("ds-cfg-java-class",
                    "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
            conn.addExpectedAttribute("ds-cfg-attribute-type", "description");
            ManagementContext ctx = LDAPManagementContext.createFromContext(conn);
            TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
            TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
            child.setMandatoryBooleanProperty(true);
            child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
            child.commit();
            Assert.fail("The add constraint failed to prevent creation of the managed object");
        } finally {
            // Clean up.
            TestCfg.removeConstraint(constraint);
        }
    }
    /**
     * Tests removal of a child managed object succeeds when registered remove
     * constraints succeed.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testRemoveConstraintSuccess() throws Exception {
        Constraint constraint = new MockConstraint(false, false, true);
        TestCfg.addConstraint(constraint);
        try {
            DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
                    "cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config");
            c.importLDIF(TEST_LDIF);
            ManagementContext ctx = LDAPManagementContext.createFromContext(c);
            TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
            parent.removeTestChild("test child 1");
            c.assertSubtreeIsDeleted();
        } finally {
            // Clean up.
            TestCfg.removeConstraint(constraint);
        }
    }
    /**
     * Tests removal of a child managed object fails when registered remove
     * constraints fails.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test(expectedExceptions = OperationRejectedException.class)
    public void testRemoveConstraintFail() throws Exception {
        Constraint constraint = new MockConstraint(true, true, false);
        TestCfg.addConstraint(constraint);
        try {
            DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
                    "cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config");
            c.importLDIF(TEST_LDIF);
            ManagementContext ctx = LDAPManagementContext.createFromContext(c);
            TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
            parent.removeTestChild("test child 1");
            Assert.fail("The remove constraint failed to prevent removal of the managed object");
        } finally {
            // Clean up.
            TestCfg.removeConstraint(constraint);
        }
    }
    /**
     * Tests modification of a child managed object succeeds when registered
     * remove constraints succeed.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test
    public void testModifyConstraintSuccess() throws Exception {
        Constraint constraint = new MockConstraint(false, true, false);
        TestCfg.addConstraint(constraint);
        try {
            ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
                    "cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config");
            c.importLDIF(TEST_LDIF);
            c.addExpectedModification("ds-cfg-base-dn");
            ManagementContext ctx = LDAPManagementContext.createFromContext(c);
            TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
            TestChildCfgClient child = parent.getTestChild("test child 2");
            child.setOptionalMultiValuedDNProperty1(Collections.<DN> emptySet());
            child.commit();
            Assert.assertTrue(c.isEntryModified());
        } finally {
            // Clean up.
            TestCfg.removeConstraint(constraint);
        }
    }
    /**
     * Tests modification of a child managed object fails when registered remove
     * constraints fails.
     *
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test(expectedExceptions = OperationRejectedException.class)
    public void testModifyConstraintFail() throws Exception {
        Constraint constraint = new MockConstraint(true, false, true);
        TestCfg.addConstraint(constraint);
        try {
            ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
                    "cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config");
            c.importLDIF(TEST_LDIF);
            c.addExpectedModification("ds-cfg-base-dn");
            ManagementContext ctx = LDAPManagementContext.createFromContext(c);
            TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
            TestChildCfgClient child = parent.getTestChild("test child 2");
            child.setOptionalMultiValuedDNProperty1(Collections.<DN> emptySet());
            child.commit();
            Assert.fail("The modify constraint failed to prevent modification of the managed object");
        } finally {
            // Clean up.
            TestCfg.removeConstraint(constraint);
        }
    }
    // Asserts that the actual set of DNs contains the expected values.
    private void assertDNSetEquals(SortedSet<DN> actual, String... expected) {
        String[] actualStrings = new String[actual.size()];
        int i = 0;
        for (DN dn : actual) {
            actualStrings[i] = dn.toString();
            i++;
        }
        Assert.assertEqualsNoOrder(actualStrings, expected);
    }
    // Create the named test parent managed object.
    private TestParentCfgClient createTestParent(ManagementContext context, String name)
            throws Exception {
        ManagedObject<RootCfgClient> root = context.getRootConfigurationManagedObject();
        return root.createChild(TestCfg.getTestOneToManyParentRelationDefinition(), TestParentCfgDefn.getInstance(),
                name, null).getConfiguration();
    }
    // Retrieve the named test parent managed object.
    private TestParentCfgClient getTestParent(ManagementContext context, String name)
            throws Exception {
        ManagedObject<RootCfgClient> root = context.getRootConfigurationManagedObject();
        return root.getChild(TestCfg.getTestOneToManyParentRelationDefinition(), name).getConfiguration();
    }
    // List test parent managed objects.
    private String[] listTestParents(ManagementContext context) throws Exception {
        ManagedObject<RootCfgClient> root = context.getRootConfigurationManagedObject();
        return root.listChildren(TestCfg.getTestOneToManyParentRelationDefinition());
    }
    // Remove the named test parent managed object.
    private void removeTestParent(ManagementContext context, String name) throws Exception {
        ManagedObject<RootCfgClient> root = context.getRootConfigurationManagedObject();
        root.removeChild(TestCfg.getTestOneToManyParentRelationDefinition(), name);
    }
}
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockConstraint.java
New file
@@ -0,0 +1,131 @@
/*
 * 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.
 */
package org.opends.server.admin.client.ldap;
import java.util.Collection;
import java.util.Collections;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.opends.server.admin.Constraint;
import org.opends.server.admin.ManagedObjectPath;
import org.opends.server.admin.client.ClientConstraintHandler;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.server.ServerConstraintHandler;
/**
 * A mock constraint which can be configured to refuse various types of
 * operation.
 */
public final class MockConstraint extends Constraint {
    /**
     * Mock client constraint handler.
     */
    private class Handler extends ClientConstraintHandler {
        /**
         * {@inheritDoc}
         */
        @Override
        public boolean isAddAcceptable(ManagementContext context, ManagedObject<?> managedObject,
                Collection<LocalizableMessage> unacceptableReasons) throws ErrorResultException {
            if (!allowAdds) {
                unacceptableReasons.add(LocalizableMessage.raw("Adds not allowed"));
            }
            return allowAdds;
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public boolean isDeleteAcceptable(ManagementContext context, ManagedObjectPath<?, ?> path,
                Collection<LocalizableMessage> unacceptableReasons) throws ErrorResultException {
            if (!allowDeletes) {
                unacceptableReasons.add(LocalizableMessage.raw("Deletes not allowed"));
            }
            return allowDeletes;
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public boolean isModifyAcceptable(ManagementContext context, ManagedObject<?> managedObject,
                Collection<LocalizableMessage> unacceptableReasons) throws ErrorResultException {
            if (!allowModifies) {
                unacceptableReasons.add(LocalizableMessage.raw("Modifies not allowed"));
            }
            return allowModifies;
        }
    }
    // Determines if add operations are allowed.
    private final boolean allowAdds;
    // Determines if modify operations are allowed.
    private final boolean allowModifies;
    // Determines if delete operations are allowed.
    private final boolean allowDeletes;
    /**
     * Creates a new mock constraint.
     *
     * @param allowAdds
     *            Determines if add operations are allowed.
     * @param allowModifies
     *            Determines if modify operations are allowed.
     * @param allowDeletes
     *            Determines if delete operations are allowed.
     */
    public MockConstraint(boolean allowAdds, boolean allowModifies, boolean allowDeletes) {
        this.allowAdds = allowAdds;
        this.allowModifies = allowModifies;
        this.allowDeletes = allowDeletes;
    }
    /**
     * {@inheritDoc}
     */
    public Collection<ClientConstraintHandler> getClientConstraintHandlers() {
        return Collections.<ClientConstraintHandler> singleton(new Handler());
    }
    /**
     * {@inheritDoc}
     */
    public Collection<ServerConstraintHandler> getServerConstraintHandlers() {
        return Collections.emptySet();
    }
}
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockLDAPConnection.java
New file
@@ -0,0 +1,386 @@
/*
 * 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 2007-2008 Sun Microsystems, Inc.
 */
package org.opends.server.admin.client.ldap;
import static org.fest.assertions.Assertions.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.AttributeDescription;
import org.forgerock.opendj.ldap.AttributeParser;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.DecodeException;
import org.forgerock.opendj.ldap.DecodeOptions;
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.LinkedHashMapEntry;
import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.TestCaseUtils;
import org.forgerock.opendj.ldap.controls.Control;
import org.forgerock.opendj.ldap.controls.ControlDecoder;
import org.forgerock.opendj.ldap.requests.ModifyRequest;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
/**
 * A mock LDAP connection which fakes up search results based on some LDIF
 * content. Implementations should override the modify operations in order to
 * get provide the correct fake behavior.
 */
public class MockLDAPConnection extends LDAPConnection {
    /**
     * A mock entry.
     */
    private static final class MockEntry {
        private final Entry entry;
        private final List<MockEntry> children;
        private final DN dn;
        public MockEntry(DN dn, Entry entry) {
            this.dn = dn;
            this.entry = entry;
            this.children = new LinkedList<MockEntry>();
        }
        public Entry getEntry() {
            return entry;
        }
        public List<MockEntry> getChildren() {
            return children;
        }
        public DN getDN() {
            return dn;
        }
        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append("dn:");
            builder.append(dn);
            builder.append(", attributes:");
            builder.append(entry.getAllAttributes());
            return builder.toString();
        }
    }
    /** All the entries. */
    private final Map<DN, MockEntry> entries;
    /** The single root entry. */
    private final MockEntry rootEntry;
    /**
     * Create a mock connection.
     */
    public MockLDAPConnection() {
        this.rootEntry = new MockEntry(DN.rootDN(), new LinkedHashMapEntry(DN.rootDN()));
        this.entries = new HashMap<DN, MockEntry>();
        this.entries.put(DN.rootDN(), this.rootEntry);
    }
    /**
     * {@inheritDoc}
     */
    public void createEntry(Entry entry) throws ErrorResultException {
        throw new UnsupportedOperationException("createEntry");
    }
    /**
     * {@inheritDoc}
     */
    public void deleteSubtree(DN dn) throws ErrorResultException {
        throw new UnsupportedOperationException("deleteSubtree");
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean entryExists(DN dn) throws ErrorResultException {
        return getEntry(dn) != null;
    }
    /**
     * Imports the provided LDIF into this mock connection.
     *
     * @param lines
     *            The LDIF.
     */
    public final void importLDIF(String... lines) {
        try {
            for (Entry entry : TestCaseUtils.makeEntries(lines)) {
                addEntry(entry);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<DN> listEntries(DN dn, String filter) throws ErrorResultException {
        MockEntry entry = getEntry(dn);
        if (entry == null) {
            throw ErrorResultException.newErrorResult(ResultCode.NO_SUCH_OBJECT, "Could not find entry: " + dn);
        } else {
            List<DN> names = new LinkedList<DN>();
            for (MockEntry child : entry.children) {
                names.add(DN.valueOf(child.getDN().toString()));
            }
            return names;
        }
    }
    /**
     * {@inheritDoc}
     */
    public void modifyEntry(ModifyRequest request) throws ErrorResultException {
        throw new UnsupportedOperationException("modifyEntry");
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public SearchResultEntry readEntry(DN dn, Collection<String> attrIds) throws ErrorResultException {
        final MockEntry entry = getEntry(dn);
        return new SearchResultEntry() {
            public AttributeParser parseAttribute(String attributeDescription) {
                throw new RuntimeException("not implemented");
            }
            public AttributeParser parseAttribute(AttributeDescription attributeDescription) {
                throw new RuntimeException("not implemented");
            }
            public boolean containsControl(String oid) {
                return false;
            }
            public SearchResultEntry setName(String dn) {
                throw new RuntimeException("not implemented");
            }
            @Override
            public SearchResultEntry setName(DN dn) {
                throw new RuntimeException("not implemented");
            }
            @Override
            public SearchResultEntry replaceAttribute(String attributeDescription, Object... values) {
                throw new RuntimeException("not implemented");
            }
            @Override
            public boolean replaceAttribute(Attribute attribute) {
                throw new RuntimeException("not implemented");
            }
            @Override
            public SearchResultEntry removeAttribute(String attributeDescription, Object... values) {
                throw new RuntimeException("not implemented");
            }
            @Override
            public boolean removeAttribute(AttributeDescription attributeDescription) {
                throw new RuntimeException("not implemented");
            }
            @Override
            public boolean removeAttribute(Attribute attribute, Collection<? super ByteString> missingValues) {
                throw new RuntimeException("not implemented");
            }
            @Override
            public DN getName() {
                return entry.getDN();
            }
            @Override
            public List<Control> getControls() {
                throw new RuntimeException("not implemented");
            }
            @Override
            public <C extends Control> C getControl(ControlDecoder<C> decoder, DecodeOptions options) throws DecodeException {
                throw new RuntimeException("not implemented");
            }
            @Override
            public int getAttributeCount() {
                return entry.getEntry().getAttributeCount();
            }
            @Override
            public Attribute getAttribute(String attributeDescription) {
                return entry.getEntry().getAttribute(attributeDescription);
            }
            @Override
            public Attribute getAttribute(AttributeDescription attributeDescription) {
                return entry.getEntry().getAttribute(attributeDescription);
            }
            @Override
            public Iterable<Attribute> getAllAttributes(String attributeDescription) {
                return entry.getEntry().getAllAttributes(attributeDescription);
            }
            @Override
            public Iterable<Attribute> getAllAttributes(AttributeDescription attributeDescription) {
                return entry.getEntry().getAllAttributes(attributeDescription);
            }
            @Override
            public Iterable<Attribute> getAllAttributes() {
                return entry.getEntry().getAllAttributes();
            }
            @Override
            public boolean containsAttribute(String attributeDescription, Object... values) {
                return entry.getEntry().containsAttribute(attributeDescription, values);
            }
            @Override
            public boolean containsAttribute(Attribute attribute, Collection<? super ByteString> missingValues) {
                throw new RuntimeException("not implemented");
            }
            @Override
            public SearchResultEntry clearAttributes() {
                throw new RuntimeException("not implemented");
            }
            @Override
            public SearchResultEntry addControl(Control control) {
                throw new RuntimeException("not implemented");
            }
            @Override
            public SearchResultEntry addAttribute(String attributeDescription, Object... values) {
                throw new RuntimeException("not implemented");
            }
            @Override
            public boolean addAttribute(Attribute attribute, Collection<? super ByteString> duplicateValues) {
                throw new RuntimeException("not implemented");
            }
            @Override
            public boolean addAttribute(Attribute attribute) {
                throw new RuntimeException("not implemented");
            }
        };
    }
    /**
     * Asserts whether the provided attribute contains exactly the set of values
     * contained in the provided collection.
     *
     * @param attr
     *            The attribute.
     * @param values
     *            The expected values.
     * @throws ErrorResultException
     *             If an unexpected problem occurred.
     */
    protected final void assertAttributeEquals(Attribute attr, Collection<String> values) throws ErrorResultException {
        List<String> actualValues = new LinkedList<String>();
        for (ByteString actualValue : attr) {
            actualValues.add(actualValue.toString());
        }
        assertThat(actualValues).hasSize(values.size());
        assertThat(actualValues).containsOnly(values.toArray());
    }
    /**
     * Create a new mock entry.
     *
     * @param entry
     *            The entry to be added.
     */
    private void addEntry(Entry entry) {
        MockEntry parent = rootEntry;
        DN entryDN = entry.getName();
        // Create required glue entries.
        for (int i = 0; i < entryDN.size() - 1; i++) {
            RDN rdn = entryDN.parent(entryDN.size() - i - 1).rdn();
            DN dn = parent.getDN().child(rdn);
            if (!entries.containsKey(dn)) {
                MockEntry glue = new MockEntry(dn, new LinkedHashMapEntry(dn));
                parent.getChildren().add(glue);
                entries.put(dn, glue);
            }
            parent = entries.get(dn);
        }
        // We now have the parent entry - so construct the new entry.
        MockEntry child = new MockEntry(entryDN, LinkedHashMapEntry.deepCopyOfEntry(entry));
        parent.getChildren().add(child);
        entries.put(entryDN, child);
    }
    /**
     * Gets the named entry.
     *
     * @param dn
     *            The name of the entry.
     * @return Returns the mock entry or <code>null</code> if it does not exist.
     */
    private MockEntry getEntry(DN dn) {
        DN name = DN.valueOf(dn.toString());
        return entries.get(name);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void unbind() {
        // nothing to do
    }
}
opendj-admin/src/test/java/org/opends/server/admin/client/ldap/ModifyEntryMockLDAPConnection.java
New file
@@ -0,0 +1,115 @@
/*
 * 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.
 */
package org.opends.server.admin.client.ldap;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.Modification;
import org.forgerock.opendj.ldap.requests.ModifyRequest;
import org.testng.Assert;
import com.forgerock.opendj.util.Validator;
/**
 * A mock LDAP connection which is used to verify that a modify operation was
 * requested and that it has the correct parameters.
 */
public final class ModifyEntryMockLDAPConnection extends MockLDAPConnection {
    // Detect multiple calls.
    private boolean alreadyModified = false;
    private final DN expectedDN;
    // The expected set of modifications (attribute name -> list of
    // values).
    private final Map<String, List<String>> modifications = new HashMap<String, List<String>>();
    /**
     * Create a new mock ldap connection for detecting modify operations.
     *
     * @param dn
     *            The expected DN of the entry to be added.
     */
    public ModifyEntryMockLDAPConnection(String dn) {
        this.expectedDN = DN.valueOf(dn);
    }
    /**
     * Add a modification which should be part of the modify operation.
     *
     * @param expectedName
     *            The name of the expected attribute.
     * @param expectedValues
     *            The attribute's expected new values (possibly empty if
     *            deleted).
     */
    public void addExpectedModification(String expectedName, String... expectedValues) {
        Validator.ensureNotNull(expectedName);
        Validator.ensureNotNull(expectedValues);
        modifications.put(expectedName, Arrays.asList(expectedValues));
    }
    /**
     * Determines whether or not the entry was modified.
     *
     * @return Returns <code>true</code> if it was modified.
     */
    public boolean isEntryModified() {
        return alreadyModified;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void modifyEntry(ModifyRequest request) throws ErrorResultException {
        Assert.assertFalse(alreadyModified);
        Assert.assertEquals(request.getName(), expectedDN);
        Map<String, List<String>> expected = new HashMap<String, List<String>>(modifications);
        for (Modification modification : request.getModifications()) {
            Attribute attribute = modification.getAttribute();
            String attrName = attribute.getAttributeDescription().getAttributeType().getNameOrOID();
            List<String> values = expected.remove(attrName);
            if (values == null) {
                Assert.fail("Unexpected modification to attribute " + attrName);
            }
            assertAttributeEquals(attribute, values);
        }
        if (!expected.isEmpty()) {
            Assert.fail("Missing modifications to: " + expected.keySet());
        }
        alreadyModified = true;
    }
}