/*
* 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.
* Portions copyright 2011-2013 ForgeRock AS.
*/
package org.opends.server.core;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import org.testng.annotations.Test;
import org.testng.annotations.AfterMethod;
import org.opends.server.TestCaseUtils;
import org.opends.messages.Message;
import org.opends.server.api.Backend;
import org.opends.server.plugins.DisconnectClientPlugin;
import org.opends.server.plugins.ShortCircuitPlugin;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.ldap.BindRequestProtocolOp;
import org.opends.server.protocols.ldap.BindResponseProtocolOp;
import org.opends.server.protocols.ldap.DeleteRequestProtocolOp;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.tools.LDAPDelete;
import org.opends.server.tools.LDAPWriter;
import org.opends.server.types.*;
import org.opends.server.workflowelement.localbackend.LocalBackendDeleteOperation;
import static org.testng.Assert.*;
import static org.opends.server.protocols.ldap.LDAPConstants.*;
/**
* A set of test cases for delete operations
*/
public class DeleteOperationTestCase
extends OperationTestCase
{
// Some of the tests disable the backends, so we reenable them here.
@AfterMethod(alwaysRun=true)
public void reenableBackend() throws DirectoryException {
Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
b.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* {@inheritDoc}
*/
@Override()
protected Operation[] createTestOperations()
throws Exception
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
return new Operation[]
{
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
new ArrayList<Control>(), ByteString.empty()),
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, ByteString.empty()),
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf("o=test")),
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, ByteString.valueOf("o=test")),
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
new ArrayList<Control>(), DN.nullDN()),
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, DN.nullDN()),
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
new ArrayList<Control>(), DN.decode("o=test")),
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, DN.decode("o=test"))
};
}
/**
* Tests the <CODE>getRawEntryDN</CODE> and <CODE>setRawEntryDN</CODE>
* methods.
*
* @param deleteOperation The delete operation to use in the test.
*/
@Test(dataProvider = "testOperations")
public void testGetAndSetRawEntryDN(DeleteOperation deleteOperation)
{
ByteString originalRawDN = deleteOperation.getRawEntryDN();
assertNotNull(originalRawDN);
deleteOperation.setRawEntryDN(ByteString.valueOf("dc=example,dc=com"));
assertEquals(deleteOperation.getRawEntryDN(),
ByteString.valueOf("dc=example,dc=com"));
deleteOperation.setRawEntryDN(originalRawDN);
assertEquals(deleteOperation.getRawEntryDN(), originalRawDN);
}
/**
* Tests the <CODE>getEntryDN</CODE> method that should decode the rawEntryDN
* to compute the entryDN.
*/
@Test()
public void testGetEntryDNNull()
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, ByteString.valueOf("o=test"));
assertNotNull(deleteOperation.getEntryDN());
}
/**
* Tests the <CODE>getEntryDN</CODE> method when it should not be null.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testGetEntryDNNotNull()
throws Exception
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, DN.decode("o=test"));
assertNotNull(deleteOperation.getEntryDN());
}
/**
* Tests the <CODE>getEntryDN</CODE> method when it originally started as
* non-null, then was changed to null; because of the call to the
* <CODE>setRawEntry<CODE> method, and becomes non-null again because
* of the call to the <CODE>getEntryDN</CODE> again.
*
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testGetEntryDNChangedToNull()
throws Exception
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, DN.decode("o=test"));
assertNotNull(deleteOperation.getEntryDN());
deleteOperation.setRawEntryDN(ByteString.valueOf("dc=example,dc=com"));
assertNotNull(deleteOperation.getEntryDN());
}
/**
* Retrieves a number of generic elements from a completed delete operation.
* It should have completed successfully.
*/
private void retrieveCompletedOperationElements(
DeleteOperation deleteOperation)
throws Exception
{
assertTrue(deleteOperation.getProcessingStartTime() > 0);
assertTrue(deleteOperation.getProcessingStopTime() >=
deleteOperation.getProcessingStartTime());
assertTrue(deleteOperation.getProcessingTime() >= 0);
assertNotNull(deleteOperation.getResponseLogElements());
long changeNumber = deleteOperation.getChangeNumber();
deleteOperation.setChangeNumber(changeNumber);
}
/**
* Tests the <CODE>getEntryToDelete</CODE> method for a successful delete
* operation.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testGetEntryToDeleteExists()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("o=test"));
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(deleteOperation);
List localOps =
(List) (deleteOperation.getAttachment(Operation.LOCALBACKENDOPERATIONS));
assertNotNull(localOps);
for (Object localOp : localOps){
LocalBackendDeleteOperation curOp = (LocalBackendDeleteOperation) localOp;
assertNotNull(curOp.getEntryToDelete());
}
}
/**
* Tests the <CODE>getEntryToDelete</CODE> method for a delete operation that
* fails because the target entry doesn't exist.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testGetEntryToDeleteNonExistent()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("ou=People,o=test"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
List localOps =
(List) (deleteOperation.getAttachment(Operation.LOCALBACKENDOPERATIONS));
assertNotNull(localOps);
for (Object localOp : localOps){
LocalBackendDeleteOperation curOp = (LocalBackendDeleteOperation) localOp;
assertNull(curOp.getEntryToDelete());
}
}
/**
* Tests an external delete operation.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testExternalDelete()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"o=test"
};
assertEquals(LDAPDelete.mainDelete(args, false, null, null), 0);
}
/**
* Tests the delete operation with a valid raw DN that is a suffix.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithValidRawDNSuffix()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("o=test"));
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(deleteOperation);
}
/**
* Tests the delete operation with a valid processed DN that is a suffix.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithValidProcessedDNSuffix()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(DN.decode("o=test"));
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(deleteOperation);
}
/**
* Tests the delete operation with a valid raw DN that is a leaf.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithValidRawDNLeaf()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry e = TestCaseUtils.makeEntry("dn: cn=test,o=test",
"objectClass: top",
"objectClass: device",
"cn: test");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(), e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("cn=test,o=test"));
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(deleteOperation);
}
/**
* Tests the delete operation with a valid processed DN that is a leaf.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithValidProcessedDNLeaf()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry e = TestCaseUtils.makeEntry("dn: cn=test,o=test",
"objectClass: top",
"objectClass: device",
"cn: test");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(), e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
DeleteOperation deleteOperation =
conn.processDelete(DN.decode("cn=test,o=test"));
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(deleteOperation);
}
/**
* Tests the delete operation with a malformed raw DN.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithMalformedRawDN()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("malformed"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests the delete operation with a nonexistent raw DN that should be a
* suffix.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithNonExistentSuffixRawDN()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("o=does not exist"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests the delete operation with a nonexistent processed DN that should be a
* suffix.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithNonExistentSuffixProcessedDN()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(DN.decode("o=does not exist"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests the delete operation with a raw DN below a suffix that doesn't exist.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithRawDNBelowNonExistentSuffix()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("cn=entry,o=does not exist"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests the delete operation with a processed DN below a suffix that doesn't
* exist.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithProcessedDNBelowNonExistentSuffix()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(DN.decode("cn=entry,o=does not exist"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests the delete operation with a nonexistent raw DN below a suffix that
* does exist.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithNonExistentRawDNBelowExistingSuffix()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("cn=entry,o=test"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests the delete operation with a nonexistent processed DN below a suffix
* that does exist.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithNonExistentProcessedDNBelowExistingSuffix()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(DN.decode("cn=entry,o=test"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests the delete operation for a nonleaf raw DN.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithNonLeafRawDN()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry e = TestCaseUtils.makeEntry("dn: cn=test,o=test",
"objectClass: top",
"objectClass: device",
"cn: test");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(), e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("o=test"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests the delete operation for a nonleaf processed DN.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithNonLeafProcessedDN()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry e = TestCaseUtils.makeEntry("dn: cn=test,o=test",
"objectClass: top",
"objectClass: device",
"cn: test");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(), e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("o=test"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests the delete operation when the server has a writability mode of
* disabled.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithServerWritabilityDisabled()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DirectoryServer.setWritabilityMode(WritabilityMode.DISABLED);
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("o=test"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests an internal delete operation when the server has a writability mode
* of internal-only.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalDeleteWithServerWritabilityInternalOnly()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DirectoryServer.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("o=test"));
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests an external delete operation when the server has a writability mode
* of internal-only.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testExternalDeleteWithServerWritabilityInternalOnly()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
DirectoryServer.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"o=test"
};
assertFalse(LDAPDelete.mainDelete(args, false, null, null) == 0);
DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests the delete operation when the backend has a writability mode of
* disabled.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDeleteWithBackendWritabilityDisabled()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
Backend backend = DirectoryServer.getBackend(DN.decode("o=test"));
backend.setWritabilityMode(WritabilityMode.DISABLED);
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("o=test"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
backend.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests an internal delete operation when the backend has a writability mode
* of internal-only.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalDeleteWithBackendWritabilityInternalOnly()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
Backend backend = DirectoryServer.getBackend(DN.decode("o=test"));
backend.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("o=test"));
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
backend.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests an external delete operation when the backend has a writability mode
* of internal-only.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testExternalDeleteWithBackendWritabilityInternalOnly()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Backend backend = DirectoryServer.getBackend(DN.decode("o=test"));
backend.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"o=test"
};
assertFalse(LDAPDelete.mainDelete(args, false, null, null) == 0);
backend.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests a delete operation that gets canceled before startup.
*
* @throws Exception If an unexpected probem occurs.
*/
@Test()
public void testCancelBeforeStartup()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperationBasis deleteOperation =
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, ByteString.valueOf("o=test"));
CancelRequest cancelRequest = new CancelRequest(false,
Message.raw("testCancelBeforeStartup"));
deleteOperation.abort(cancelRequest);
deleteOperation.run();
assertEquals(deleteOperation.getResultCode(), ResultCode.CANCELED);
}
/**
* Tests a delete operation that gets canceled before startup.
*
* @throws Exception If an unexpected probem occurs.
*/
@Test()
public void testCancelAfterOperation()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperationBasis deleteOperation =
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, ByteString.valueOf("o=test"));
deleteOperation.run();
CancelRequest cancelRequest = new CancelRequest(false,
Message.raw("testCancelAfterOperation"));
CancelResult cancelResult = deleteOperation.cancel(cancelRequest);
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertEquals(cancelResult.getResultCode(), ResultCode.TOO_LATE);
}
/**
* Tests a delete operation in which the server cannot obtain a lock on the
* target entry because there is already a read lock held on it.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test(groups = { "slow" })
public void testCannotLockEntry()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Lock entryLock = LockManager.lockRead(DN.decode("o=test"));
try
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("o=test"));
assertEquals(deleteOperation.getResultCode(), ResultCode.BUSY);
}
finally
{
LockManager.unlock(DN.decode("o=test"), entryLock);
}
}
/**
* Tests a delete operation that should be disconnected in a pre-parse plugin.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDisconnectInPreParseDelete()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
org.opends.server.tools.LDAPReader r = new org.opends.server.tools.LDAPReader(s);
LDAPWriter w = new LDAPWriter(s);
TestCaseUtils.configureSocket(s);
BindRequestProtocolOp bindRequest =
new BindRequestProtocolOp(ByteString.valueOf("cn=Directory Manager"),
3, ByteString.valueOf("password"));
LDAPMessage message = new LDAPMessage(1, bindRequest);
w.writeMessage(message);
message = r.readMessage();
BindResponseProtocolOp bindResponse =
message.getBindResponseProtocolOp();
assertEquals(bindResponse.getResultCode(), 0);
DeleteRequestProtocolOp deleteRequest =
new DeleteRequestProtocolOp(ByteString.valueOf("o=test"));
message = new LDAPMessage(2, deleteRequest,
DisconnectClientPlugin.createDisconnectControlList("PreParse"));
w.writeMessage(message);
message = r.readMessage();
if (message != null)
{
// If we got an element back, then it must be a notice of disconnect
// unsolicited notification.
assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
}
try
{
s.close();
} catch (Exception e) {}
}
/**
* Tests a delete operation that should be disconnected in a pre-operation
* plugin.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDisconnectInPreOperationDelete()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
org.opends.server.tools.LDAPReader r = new org.opends.server.tools.LDAPReader(s);
LDAPWriter w = new LDAPWriter(s);
TestCaseUtils.configureSocket(s);
BindRequestProtocolOp bindRequest =
new BindRequestProtocolOp(ByteString.valueOf("cn=Directory Manager"),
3, ByteString.valueOf("password"));
LDAPMessage message = new LDAPMessage(1, bindRequest);
w.writeMessage(message);
message = r.readMessage();
BindResponseProtocolOp bindResponse =
message.getBindResponseProtocolOp();
assertEquals(bindResponse.getResultCode(), 0);
DeleteRequestProtocolOp deleteRequest =
new DeleteRequestProtocolOp(ByteString.valueOf("o=test"));
message = new LDAPMessage(2, deleteRequest,
DisconnectClientPlugin.createDisconnectControlList(
"PreOperation"));
w.writeMessage(message);
message = r.readMessage();
if (message != null)
{
// If we got an element back, then it must be a notice of disconnect
// unsolicited notification.
assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
}
try
{
s.close();
} catch (Exception e) {}
}
/**
* Tests a delete operation that should be disconnected in a post-operation
* plugin.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDisconnectInPostOperationDelete()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
org.opends.server.tools.LDAPReader r = new org.opends.server.tools.LDAPReader(s);
LDAPWriter w = new LDAPWriter(s);
TestCaseUtils.configureSocket(s);
BindRequestProtocolOp bindRequest =
new BindRequestProtocolOp(ByteString.valueOf("cn=Directory Manager"),
3, ByteString.valueOf("password"));
LDAPMessage message = new LDAPMessage(1, bindRequest);
w.writeMessage(message);
message = r.readMessage();
BindResponseProtocolOp bindResponse =
message.getBindResponseProtocolOp();
assertEquals(bindResponse.getResultCode(), 0);
DeleteRequestProtocolOp deleteRequest =
new DeleteRequestProtocolOp(ByteString.valueOf("o=test"));
message = new LDAPMessage(2, deleteRequest,
DisconnectClientPlugin.createDisconnectControlList(
"PostOperation"));
w.writeMessage(message);
message = r.readMessage();
if (message != null)
{
// If we got an element back, then it must be a notice of disconnect
// unsolicited notification.
assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
}
try
{
s.close();
} catch (Exception e) {}
}
/**
* Tests a delete operation that should be disconnected in a post-response
* plugin.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDisconnectInPostResponseDelete()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
org.opends.server.tools.LDAPReader r = new org.opends.server.tools.LDAPReader(s);
LDAPWriter w = new LDAPWriter(s);
TestCaseUtils.configureSocket(s);
BindRequestProtocolOp bindRequest =
new BindRequestProtocolOp(ByteString.valueOf("cn=Directory Manager"),
3, ByteString.valueOf("password"));
LDAPMessage message = new LDAPMessage(1, bindRequest);
w.writeMessage(message);
message = r.readMessage();
BindResponseProtocolOp bindResponse =
message.getBindResponseProtocolOp();
assertEquals(bindResponse.getResultCode(), 0);
DeleteRequestProtocolOp deleteRequest =
new DeleteRequestProtocolOp(ByteString.valueOf("o=test"));
message = new LDAPMessage(2, deleteRequest,
DisconnectClientPlugin.createDisconnectControlList(
"PostResponse"));
w.writeMessage(message);
responseLoop:
while (true)
{
message = r.readMessage();
if (message == null)
{
// The connection has been closed.
break responseLoop;
}
switch (message.getProtocolOpType())
{
case OP_TYPE_DELETE_RESPONSE:
// This was expected. The disconnect didn't happen until after the
// response was sent.
break;
case OP_TYPE_EXTENDED_RESPONSE:
// The server is notifying us that it will be closing the connection.
break responseLoop;
default:
// This is a problem. It's an unexpected response.
try
{
s.close();
} catch (Exception e) {}
throw new Exception("Unexpected response message " + message +
" encountered in " +
"testDisconnectInPostResponseDelete");
}
}
try
{
s.close();
} catch (Exception e) {}
}
/**
* Tests to ensure that any registered notification listeners are invoked for
* a successful delete operation.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testSuccessWithNotificationListener()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
TestChangeNotificationListener changeListener =
new TestChangeNotificationListener();
DirectoryServer.registerChangeNotificationListener(changeListener);
assertEquals(changeListener.getAddCount(), 0);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("o=test"));
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(deleteOperation);
assertEquals(changeListener.getDeleteCount(), 1);
DirectoryServer.deregisterChangeNotificationListener(changeListener);
}
/**
* Tests to ensure that any registered notification listeners are not invoked
* for a failed delete operation.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testFailureWithNotificationListener()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
TestChangeNotificationListener changeListener =
new TestChangeNotificationListener();
DirectoryServer.registerChangeNotificationListener(changeListener);
assertEquals(changeListener.getAddCount(), 0);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
conn.processDelete(ByteString.valueOf("cn=nonexistent,o=test"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
assertEquals(changeListener.getDeleteCount(), 0);
DirectoryServer.deregisterChangeNotificationListener(changeListener);
}
/**
* Tests the behavior of the server when short-circuiting out of a delete
* operation in the pre-parse phase with a success result code.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testShortCircuitInPreParse()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
List<Control> controls =
ShortCircuitPlugin.createShortCircuitControlList(0, "PreParse");
DeleteOperationBasis deleteOperation =
new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
controls, ByteString.valueOf("o=test"));
deleteOperation.run();
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(DirectoryServer.entryExists(DN.decode("o=test")));
}
}