/*
* 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
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* 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
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.core;
import java.util.ArrayList;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
import org.opends.server.api.Backend;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.types.Attributes;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchScope;
import static org.testng.Assert.*;
import static org.opends.server.util.StaticUtils.*;
/**
* A set of generic test cases that cover adding, modifying, and removing
* Directory Server backends.
*/
public class BackendConfigManagerTestCase
extends CoreTestCase
{
/**
* Ensures that the Directory Server is running.
*
* @throws Exception If an unexpected problem occurs.
*/
@BeforeClass()
public void startServer()
throws Exception
{
TestCaseUtils.startServer();
}
/**
* Tests that the server will reject an attempt to register a base DN that is
* already defined in the server.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testRegisterBaseThatAlreadyExists()
throws Exception
{
TestCaseUtils.initializeTestBackend(false);
DN baseDN = DN.decode("o=test");
String backendID = createBackendID(baseDN);
Entry backendEntry = createBackendEntry(backendID, false, baseDN);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(backendEntry.getDN(), backendEntry.getObjectClasses(),
backendEntry.getUserAttributes(),
backendEntry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests that the server will reject an attempt to deregister a base DN that
* is not defined in the server.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test(expectedExceptions = { DirectoryException.class })
public void testDeregisterNonExistentBaseDN()
throws Exception
{
DirectoryServer.deregisterBaseDN(DN.decode("o=unregistered"));
}
/**
* Tests that the server will reject an attempt to register a base DN using a
* backend with a backend ID that is already defined in the server.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testRegisterBackendIDThatAlreadyExists()
throws Exception
{
TestCaseUtils.initializeTestBackend(false);
DN baseDN = DN.decode("o=test");
String backendID = "test";
Entry backendEntry = createBackendEntry(backendID, false, baseDN);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(backendEntry.getDN(), backendEntry.getObjectClasses(),
backendEntry.getUserAttributes(),
backendEntry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests the ability of the server to create and remove a backend that is
* never enabled.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testAddAndRemoveDisabledBackend()
throws Exception
{
DN baseDN = DN.decode("o=bcmtest");
String backendID = createBackendID(baseDN);
Entry backendEntry = createBackendEntry(backendID, false, baseDN);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(backendEntry.getDN(), backendEntry.getObjectClasses(),
backendEntry.getUserAttributes(),
backendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(backendID));
assertNull(DirectoryServer.getBackendWithBaseDN(baseDN));
DeleteOperation deleteOperation = conn.processDelete(backendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
}
/**
* Tests the ability of the server to create and remove a backend that is
* enabled. It will also test the ability of that backend to hold entries.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testAddAndRemoveEnabledBackend()
throws Exception
{
DN baseDN = DN.decode("o=bcmtest");
String backendID = createBackendID(baseDN);
Entry backendEntry = createBackendEntry(backendID, true, baseDN);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(backendEntry.getDN(), backendEntry.getObjectClasses(),
backendEntry.getUserAttributes(),
backendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
Backend backend = DirectoryServer.getBackend(backendID);
assertNotNull(backend);
assertEquals(backend, DirectoryServer.getBackendWithBaseDN(baseDN));
assertNull(backend.getParentBackend());
assertTrue(backend.getSubordinateBackends().length == 0);
assertFalse(backend.entryExists(baseDN));
assertTrue(DirectoryServer.isNamingContext(baseDN));
Entry e = createEntry(baseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(backend.entryExists(baseDN));
DeleteOperation deleteOperation = conn.processDelete(backendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(backendID));
}
/**
* Tests the ability of the server to create a backend that is disabled and
* then enable it through a configuration change, and then subsequently
* disable it.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testEnableAndDisableBackend()
throws Exception
{
// Create the backend and make it disabled.
DN baseDN = DN.decode("o=bcmtest");
String backendID = createBackendID(baseDN);
Entry backendEntry = createBackendEntry(backendID, false, baseDN);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(backendEntry.getDN(), backendEntry.getObjectClasses(),
backendEntry.getUserAttributes(),
backendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(backendID));
assertFalse(DirectoryServer.isNamingContext(baseDN));
// Modify the backend to enable it.
ArrayList<Modification> mods = new ArrayList<Modification>();
mods.add(new Modification(ModificationType.REPLACE,
Attributes.create("ds-cfg-enabled", "true")));
ModifyOperation modifyOperation =
conn.processModify(backendEntry.getDN(), mods);
assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
Backend backend = DirectoryServer.getBackend(backendID);
assertNotNull(backend);
assertEquals(backend, DirectoryServer.getBackendWithBaseDN(baseDN));
assertNull(backend.getParentBackend());
assertTrue(backend.getSubordinateBackends().length == 0);
assertFalse(backend.entryExists(baseDN));
assertTrue(DirectoryServer.isNamingContext(baseDN));
Entry e = createEntry(baseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(backend.entryExists(baseDN));
// Modify the backend to disable it.
mods = new ArrayList<Modification>();
mods.add(new Modification(ModificationType.REPLACE,
Attributes.create("ds-cfg-enabled", "false")));
modifyOperation =
conn.processModify(backendEntry.getDN(), mods);
assertNull(DirectoryServer.getBackend(backendID));
assertFalse(DirectoryServer.entryExists(baseDN));
assertFalse(DirectoryServer.isNamingContext(baseDN));
// Delete the disabled backend.
DeleteOperation deleteOperation = conn.processDelete(backendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
}
/**
* Tests the ability of the Directory Server to work properly when adding
* nested backends in which the parent is added first and the child second.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testAddNestedBackendParentFirst()
throws Exception
{
// Create the parent backend and the corresponding base entry.
DN parentBaseDN = DN.decode("o=parent");
String parentBackendID = createBackendID(parentBaseDN);
Entry parentBackendEntry = createBackendEntry(parentBackendID, true,
parentBaseDN);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(parentBackendEntry.getDN(),
parentBackendEntry.getObjectClasses(),
parentBackendEntry.getUserAttributes(),
parentBackendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
Backend parentBackend = DirectoryServer.getBackend(parentBackendID);
assertNotNull(parentBackend);
assertEquals(parentBackend,
DirectoryServer.getBackendWithBaseDN(parentBaseDN));
assertNull(parentBackend.getParentBackend());
assertTrue(parentBackend.getSubordinateBackends().length == 0);
assertFalse(parentBackend.entryExists(parentBaseDN));
assertTrue(DirectoryServer.isNamingContext(parentBaseDN));
Entry e = createEntry(parentBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(parentBackend.entryExists(parentBaseDN));
// Create the child backend and the corresponding base entry.
DN childBaseDN = DN.decode("ou=child,o=parent");
String childBackendID = createBackendID(childBaseDN);
Entry childBackendEntry = createBackendEntry(childBackendID, true,
childBaseDN);
addOperation =
conn.processAdd(childBackendEntry.getDN(),
childBackendEntry.getObjectClasses(),
childBackendEntry.getUserAttributes(),
childBackendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
Backend childBackend = DirectoryServer.getBackend(childBackendID);
assertNotNull(childBackend);
assertEquals(childBackend,
DirectoryServer.getBackendWithBaseDN(childBaseDN));
assertNotNull(childBackend.getParentBackend());
assertEquals(parentBackend, childBackend.getParentBackend());
assertTrue(parentBackend.getSubordinateBackends().length == 1);
assertFalse(childBackend.entryExists(childBaseDN));
assertFalse(DirectoryServer.isNamingContext(childBaseDN));
e = createEntry(childBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(childBackend.entryExists(childBaseDN));
// Make sure that both entries exist.
InternalSearchOperation internalSearch =
conn.processSearch(parentBaseDN, SearchScope.WHOLE_SUBTREE,
SearchFilter.createFilterFromString("(objectClass=*)"));
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
assertEquals(internalSearch.getSearchEntries().size(), 2);
// Make sure that we can't remove the parent backend with the child still
// in place.
DeleteOperation deleteOperation =
conn.processDelete(parentBackendEntry.getDN());
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
assertNotNull(DirectoryServer.getBackend(parentBackendID));
// Delete the child and then delete the parent.
deleteOperation = conn.processDelete(childBackendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(childBackendID));
assertTrue(parentBackend.getSubordinateBackends().length == 0);
deleteOperation = conn.processDelete(parentBackendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(parentBackendID));
}
/**
* Tests the ability of the Directory Server to work properly when adding
* nested backends in which the child is added first and the parent second.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testAddNestedBackendChildFirst()
throws Exception
{
// Create the child backend and the corresponding base entry (at the time
// of the creation, it will be a naming context).
DN childBaseDN = DN.decode("ou=child,o=parent");
String childBackendID = createBackendID(childBaseDN);
Entry childBackendEntry = createBackendEntry(childBackendID, true,
childBaseDN);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(childBackendEntry.getDN(),
childBackendEntry.getObjectClasses(),
childBackendEntry.getUserAttributes(),
childBackendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
Backend childBackend = DirectoryServer.getBackend(childBackendID);
assertNotNull(childBackend);
assertEquals(childBackend,
DirectoryServer.getBackendWithBaseDN(childBaseDN));
assertFalse(childBackend.entryExists(childBaseDN));
assertNull(childBackend.getParentBackend());
assertTrue(childBackend.getSubordinateBackends().length == 0);
assertFalse(childBackend.entryExists(childBaseDN));
Entry e = createEntry(childBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(childBackend.entryExists(childBaseDN));
assertTrue(DirectoryServer.isNamingContext(childBaseDN));
// Create the parent backend and the corresponding entry (and verify that
// its DN is now a naming context and the child's is not).
DN parentBaseDN = DN.decode("o=parent");
String parentBackendID = createBackendID(parentBaseDN);
Entry parentBackendEntry = createBackendEntry(parentBackendID, true,
parentBaseDN);
addOperation =
conn.processAdd(parentBackendEntry.getDN(),
parentBackendEntry.getObjectClasses(),
parentBackendEntry.getUserAttributes(),
parentBackendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
Backend parentBackend = DirectoryServer.getBackend(parentBackendID);
assertNotNull(parentBackend);
assertEquals(parentBackend,
DirectoryServer.getBackendWithBaseDN(parentBaseDN));
assertNotNull(childBackend.getParentBackend());
assertEquals(parentBackend, childBackend.getParentBackend());
assertTrue(parentBackend.getSubordinateBackends().length == 1);
e = createEntry(parentBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(parentBackend.entryExists(parentBaseDN));
assertTrue(DirectoryServer.isNamingContext(parentBaseDN));
assertFalse(DirectoryServer.isNamingContext(childBaseDN));
// Verify that we can see both entries with a subtree search.
InternalSearchOperation internalSearch =
conn.processSearch(parentBaseDN, SearchScope.WHOLE_SUBTREE,
SearchFilter.createFilterFromString("(objectClass=*)"));
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
assertEquals(internalSearch.getSearchEntries().size(), 2);
// Delete the backends from the server.
DeleteOperation deleteOperation =
conn.processDelete(childBackendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(childBackendID));
assertTrue(parentBackend.getSubordinateBackends().length == 0);
deleteOperation = conn.processDelete(parentBackendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(parentBackendID));
}
/**
* Tests the ability of the Directory Server to work properly when inserting
* an intermediate backend between a parent backend and an existing nested
* backend.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInsertIntermediateBackend()
throws Exception
{
// Add the parent backend to the server and its corresponding base entry.
DN parentBaseDN = DN.decode("o=parent");
String parentBackendID = createBackendID(parentBaseDN);
Entry parentBackendEntry = createBackendEntry(parentBackendID, true,
parentBaseDN);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(parentBackendEntry.getDN(),
parentBackendEntry.getObjectClasses(),
parentBackendEntry.getUserAttributes(),
parentBackendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
Backend parentBackend = DirectoryServer.getBackend(parentBackendID);
assertNotNull(parentBackend);
assertEquals(parentBackend,
DirectoryServer.getBackendWithBaseDN(parentBaseDN));
assertNull(parentBackend.getParentBackend());
assertTrue(parentBackend.getSubordinateBackends().length == 0);
assertFalse(parentBackend.entryExists(parentBaseDN));
Entry e = createEntry(parentBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(parentBackend.entryExists(parentBaseDN));
assertTrue(DirectoryServer.isNamingContext(parentBaseDN));
// Add the grandchild backend to the server.
DN grandchildBaseDN = DN.decode("ou=grandchild,ou=child,o=parent");
String grandchildBackendID = createBackendID(grandchildBaseDN);
Entry grandchildBackendEntry = createBackendEntry(grandchildBackendID, true,
grandchildBaseDN);
addOperation =
conn.processAdd(grandchildBackendEntry.getDN(),
grandchildBackendEntry.getObjectClasses(),
grandchildBackendEntry.getUserAttributes(),
grandchildBackendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
Backend grandchildBackend = DirectoryServer.getBackend(grandchildBackendID);
assertNotNull(grandchildBackend);
assertEquals(grandchildBackend,
DirectoryServer.getBackendWithBaseDN(grandchildBaseDN));
assertNotNull(grandchildBackend.getParentBackend());
assertEquals(grandchildBackend.getParentBackend(), parentBackend);
assertTrue(parentBackend.getSubordinateBackends().length == 1);
assertFalse(grandchildBackend.entryExists(grandchildBaseDN));
// Verify that we can't create the grandchild base entry because its parent
// doesn't exist.
e = createEntry(grandchildBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.NO_SUCH_OBJECT);
assertFalse(grandchildBackend.entryExists(grandchildBaseDN));
// Add the child backend to the server and create its base entry.
DN childBaseDN = DN.decode("ou=child,o=parent");
String childBackendID = createBackendID(childBaseDN);
Entry childBackendEntry = createBackendEntry(childBackendID, true,
childBaseDN);
addOperation =
conn.processAdd(childBackendEntry.getDN(),
childBackendEntry.getObjectClasses(),
childBackendEntry.getUserAttributes(),
childBackendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
Backend childBackend = DirectoryServer.getBackend(childBackendID);
assertNotNull(childBackend);
assertEquals(childBackend,
DirectoryServer.getBackendWithBaseDN(childBaseDN));
assertNotNull(childBackend.getParentBackend());
assertEquals(parentBackend, childBackend.getParentBackend());
assertTrue(parentBackend.getSubordinateBackends().length == 1);
assertFalse(childBackend.entryExists(childBaseDN));
assertTrue(childBackend.getSubordinateBackends().length == 1);
assertEquals(childBackend.getSubordinateBackends()[0], grandchildBackend);
assertEquals(grandchildBackend.getParentBackend(), childBackend);
e = createEntry(childBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(childBackend.entryExists(childBaseDN));
// Now we can create the grandchild base entry.
e = createEntry(grandchildBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(grandchildBackend.entryExists(grandchildBaseDN));
// Verify that a subtree search can see all three entries.
InternalSearchOperation internalSearch =
conn.processSearch(parentBaseDN, SearchScope.WHOLE_SUBTREE,
SearchFilter.createFilterFromString("(objectClass=*)"));
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
assertEquals(internalSearch.getSearchEntries().size(), 3);
// Disable the intermediate (child) backend. This should be allowed.
ArrayList<Modification> mods = new ArrayList<Modification>();
mods.add(new Modification(ModificationType.REPLACE,
Attributes.create("ds-cfg-enabled",
"false")));
ModifyOperation modifyOperation =
conn.processModify(childBackendEntry.getDN(), mods);
assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
// Make sure that we now only see two entries with the subtree search
// (and those two entries should be the parent and grandchild base entries).
internalSearch =
conn.processSearch(parentBaseDN, SearchScope.WHOLE_SUBTREE,
SearchFilter.createFilterFromString("(objectClass=*)"));
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
assertEquals(internalSearch.getSearchEntries().size(), 2);
// Re-enable the intermediate backend.
mods = new ArrayList<Modification>();
mods.add(new Modification(ModificationType.REPLACE,
Attributes.create("ds-cfg-enabled", "true")));
modifyOperation = conn.processModify(childBackendEntry.getDN(), mods);
assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
// Update our reference to the child backend since the old one is no longer
// valid, and make sure that it got re-inserted back into the same place in
// the hierarchy.
childBackend = DirectoryServer.getBackend(childBackendID);
assertNotNull(childBackend);
assertEquals(childBackend,
DirectoryServer.getBackendWithBaseDN(childBaseDN));
assertNotNull(childBackend.getParentBackend());
assertEquals(parentBackend, childBackend.getParentBackend());
assertTrue(parentBackend.getSubordinateBackends().length == 1);
assertFalse(childBackend.entryExists(childBaseDN));
assertTrue(childBackend.getSubordinateBackends().length == 1);
assertEquals(childBackend.getSubordinateBackends()[0], grandchildBackend);
assertEquals(grandchildBackend.getParentBackend(), childBackend);
// Since the memory backend that we're using for this test doesn't retain
// entries across stops and restarts, a subtree search below the parent
// should still only return two entries, which means that it's going through
// the entire chain of backends.
internalSearch =
conn.processSearch(parentBaseDN, SearchScope.WHOLE_SUBTREE,
SearchFilter.createFilterFromString("(objectClass=*)"));
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
assertEquals(internalSearch.getSearchEntries().size(), 2);
// Add the child entry back into the server to get things back to the way
// they were before we disabled the backend.
e = createEntry(childBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(childBackend.entryExists(childBaseDN));
// We should again be able to see all three entries when performing a
// search.
internalSearch =
conn.processSearch(parentBaseDN, SearchScope.WHOLE_SUBTREE,
SearchFilter.createFilterFromString("(objectClass=*)"));
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
assertEquals(internalSearch.getSearchEntries().size(), 3);
// Get rid of the entries in the proper order.
DeleteOperation deleteOperation =
conn.processDelete(grandchildBackendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(grandchildBackendID));
assertTrue(childBackend.getSubordinateBackends().length == 0);
assertTrue(parentBackend.getSubordinateBackends().length == 1);
deleteOperation = conn.processDelete(childBackendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(childBackendID));
assertTrue(parentBackend.getSubordinateBackends().length == 0);
deleteOperation = conn.processDelete(parentBackendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(parentBackendID));
}
/**
* Creates an entry that may be used to add a new backend to the server. It
* will be an instance of the memory backend.
*
* @param backendID The backend ID to use for the backend.
* @param enabled Indicates whether the backend should be enabled.
* @param baseDNs The set of base DNs to use for the new backend.
*
* @return An entry that may be used to add a new backend to the server.
*
* @throws Exception If an unexpected problem occurs.
*/
private Entry createBackendEntry(String backendID, boolean enabled,
DN... baseDNs)
throws Exception
{
assertNotNull(baseDNs);
assertFalse(baseDNs.length == 0);
ArrayList<String> lines = new ArrayList<String>();
lines.add("dn: ds-cfg-backend-id=" + backendID + ",cn=Backends,cn=config");
lines.add("objectClass: top");
lines.add("objectClass: ds-cfg-backend");
lines.add("objectClass: ds-cfg-memory-backend");
lines.add("ds-cfg-backend-id: " + backendID);
lines.add("ds-cfg-java-class: org.opends.server.backends.MemoryBackend");
lines.add("ds-cfg-enabled: " + String.valueOf(enabled));
lines.add("ds-cfg-writability-mode: enabled");
for (DN dn : baseDNs)
{
lines.add("ds-cfg-base-dn: " + dn.toString());
}
String[] lineArray = new String[lines.size()];
lines.toArray(lineArray);
return TestCaseUtils.makeEntry(lineArray);
}
/**
* Constructs a backend ID to use for a backend with the provided set of base
* DNs.
*
* @param baseDNs The set of base DNs to use when creating the backend ID.
*
* @return The constructed backend ID based on the given base DNs.
*/
private String createBackendID(DN... baseDNs)
{
StringBuilder buffer = new StringBuilder();
for (DN dn : baseDNs)
{
if (buffer.length() > 0)
{
buffer.append("___");
}
String ndn = dn.toNormalizedString();
for (int i=0; i < ndn.length(); i++)
{
char c = ndn.charAt(i);
if (Character.isLetterOrDigit(c))
{
buffer.append(c);
}
else
{
buffer.append('_');
}
}
}
return buffer.toString();
}
}