/*
* 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 static org.opends.server.protocols.ldap.LDAPConstants.*;
import static org.testng.Assert.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import org.opends.messages.Message;
import org.opends.server.TestCaseUtils;
import org.opends.server.api.Backend;
import org.opends.server.plugins.DisconnectClientPlugin;
import org.opends.server.plugins.ShortCircuitPlugin;
import org.opends.server.plugins.UpdatePreOpPlugin;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.ldap.AddRequestProtocolOp;
import org.opends.server.protocols.ldap.AddResponseProtocolOp;
import org.opends.server.protocols.ldap.BindRequestProtocolOp;
import org.opends.server.protocols.ldap.BindResponseProtocolOp;
import org.opends.server.protocols.ldap.LDAPAttribute;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.tools.LDAPModify;
import org.opends.server.tools.LDAPReader;
import org.opends.server.tools.LDAPWriter;
import org.opends.server.types.*;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
* A set of test cases for add operations
*/
public class AddOperationTestCase
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);
}
/**
* Retrieves a set of add operations that may be used for testing.
*
* @return A set of add operations that may be used for testing.
*
* @throws Exception If an unexpected problem occurs.
*/
@DataProvider(name = "addOperations")
public Object[][] getAddOperations()
throws Exception
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
ArrayList<Control> noControls = new ArrayList<Control>();
ArrayList<RawAttribute> ldapAttrList = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
ldapAttrList.add(new LDAPAttribute("objectclass", values));
values.clear();
values.add(ByteString.valueOf("People"));
ldapAttrList.add(new LDAPAttribute("ou", values));
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
Operation[] opArray = new Operation[]
{
new AddOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, ByteString.valueOf("ou=People,o=test"),
ldapAttrList),
new AddOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
noControls, ByteString.valueOf("ou=People,o=test"),
ldapAttrList),
new AddOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes()),
new AddOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
noControls, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes()),
};
Object[][] objArray = new Object[opArray.length][1];
for (int i=0; i < opArray.length; i++)
{
objArray[i][0] = opArray[i];
}
return objArray;
}
/**
* {@inheritDoc}
*/
@Override()
protected Operation[] createTestOperations()
throws Exception
{
Object[][] objs = getAddOperations();
Operation[] ops = new Operation[objs.length];
for (int i=0; i < objs.length; i++)
{
ops[i] = (Operation) objs[i][0];
}
return ops;
}
/**
* Tests the <CODE>getRawEntryDN</CODE> and <CODE>setRawEntryDN</CODE>
* methods.
*
* @param addOperation The add operation to be tested.
*/
@Test(dataProvider = "addOperations")
public void testGetAndSetRawEntryDN(AddOperation addOperation)
{
ByteString originalDN = addOperation.getRawEntryDN();
assertNotNull(originalDN);
addOperation.setRawEntryDN(ByteString.valueOf("uid=test,o=test"));
assertNotNull(addOperation.getRawEntryDN());
assertEquals(addOperation.getRawEntryDN(),
ByteString.valueOf("uid=test,o=test"));
addOperation.setRawEntryDN(originalDN);
assertNotNull(addOperation.getRawEntryDN());
assertEquals(addOperation.getRawEntryDN(), originalDN);
}
/**
* Tests the <CODE>getEntryDN</CODE> method for the case in which we expect
* the rawEntryDN to be decoded.
*/
@Test()
public void testGetEntryDNInitiallyNull()
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
ArrayList<RawAttribute> ldapAttrList = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
ldapAttrList.add(new LDAPAttribute("objectclass", values));
values.clear();
values.add(ByteString.valueOf("People"));
ldapAttrList.add(new LDAPAttribute("ou", values));
AddOperationBasis addOperation =
new AddOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, ByteString.valueOf("ou=People,o=test"),
ldapAttrList);
assertNotNull(addOperation.getEntryDN());
}
/**
* Tests the <CODE>getEntryDN</CODE> method for the case in which we expect
* the DN to be initially non-null.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testGetEntryDNInitiallyNonNull()
throws Exception
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
AddOperationBasis addOperation =
new AddOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertNotNull(addOperation.getEntryDN());
}
/**
* Tests the <CODE>getEntryDN</CODE> method for the case in which we expect
* the DN to be initially non-null but then becomes null after the raw DN is
* changed, and <CODE>getEntryDN</CODE> method recomputes it again
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testGetEntryDNNonNullChangedToNull()
throws Exception
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
AddOperationBasis addOperation =
new AddOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertNotNull(addOperation.getEntryDN());
addOperation.setRawEntryDN(ByteString.valueOf("ou=Users,o=test"));
assertNotNull(addOperation.getEntryDN());
}
/**
* Tests the <CODE>getRawAttributes</CODE>, <CODE>addRawAttribute</CODE>, and
* <CODE>setRawAttributes</CODE> methods.
*
* @param addOperation The add operation to be tested.
*/
@Test(dataProvider = "addOperations")
public void testGetAndSetRawAttributes(AddOperation addOperation)
{
List<RawAttribute> rawAttrs = addOperation.getRawAttributes();
assertNotNull(rawAttrs);
assertFalse(rawAttrs.isEmpty());
ArrayList<RawAttribute> copiedAttrs =
new ArrayList<RawAttribute>(rawAttrs);
addOperation.setRawAttributes(copiedAttrs);
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("foo"));
addOperation.addRawAttribute(new LDAPAttribute("description", values));
boolean found = false;
for (RawAttribute a : addOperation.getRawAttributes())
{
if (a.getAttributeType().equalsIgnoreCase("description"))
{
found = true;
break;
}
}
assertTrue(found);
addOperation.setRawAttributes(rawAttrs);
found = false;
for (RawAttribute a : addOperation.getRawAttributes())
{
if (a.getAttributeType().equalsIgnoreCase("description"))
{
found = true;
break;
}
}
assertFalse(found);
}
/**
* Tests the <CODE>addObjectClass</CODE> method.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testAddObjectClass()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
UpdatePreOpPlugin.reset();
ObjectClass oc = DirectoryServer.getObjectClass("extensibleobject", true);
UpdatePreOpPlugin.addObjectClassToAdd(oc);
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
Entry e = DirectoryServer.getEntry(DN.decode("ou=People,o=test"));
assertTrue(e.hasObjectClass(oc));
UpdatePreOpPlugin.reset();
}
/**
* Tests the <CODE>removeObjectClass</CODE> method.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testRemoveObjectClass()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"objectClass: extensibleObject",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
UpdatePreOpPlugin.reset();
ObjectClass oc = DirectoryServer.getObjectClass("extensibleobject", true);
UpdatePreOpPlugin.addObjectClassToRemove(oc);
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
Entry e = DirectoryServer.getEntry(DN.decode("ou=People,o=test"));
assertFalse(e.hasObjectClass(oc));
UpdatePreOpPlugin.reset();
}
/**
* Tests the <CODE>setAttribute</CODE> method for an attribute that already
* exists.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testSetAttributeOverwrite()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People",
"description: foo");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
UpdatePreOpPlugin.reset();
Attribute a = Attributes.create("description", "bar");
UpdatePreOpPlugin.addAttributeToSet(a);
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
Entry e = DirectoryServer.getEntry(DN.decode("ou=People,o=test"));
List<Attribute> attrList = e.getAttribute(a.getAttributeType());
assertNotNull(attrList);
assertFalse(attrList.isEmpty());
boolean foundFoo = false;
boolean foundBar = false;
for (Attribute attr : attrList)
{
if (attr.contains(AttributeValues.create(a.getAttributeType(),
ByteString.valueOf("foo"))))
{
foundFoo = true;
}
if (attr.contains(AttributeValues.create(a.getAttributeType(),
ByteString.valueOf("bar"))))
{
foundBar = true;
}
}
assertFalse(foundFoo);
assertTrue(foundBar);
UpdatePreOpPlugin.reset();
}
/**
* Tests the <CODE>setAttribute</CODE> method for an attribute that doesn't
* exist.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testSetAttributeAdd()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
UpdatePreOpPlugin.reset();
Attribute a = Attributes.create("description", "foo");
UpdatePreOpPlugin.addAttributeToSet(a);
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
Entry e = DirectoryServer.getEntry(DN.decode("ou=People,o=test"));
List<Attribute> attrList = e.getAttribute(a.getAttributeType());
assertNotNull(attrList);
assertFalse(attrList.isEmpty());
UpdatePreOpPlugin.reset();
}
/**
* Tests the <CODE>removeAttribute</CODE> method.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testSetAttributeRemove()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People",
"description: foo");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
UpdatePreOpPlugin.reset();
AttributeType attrType = DirectoryServer.getAttributeType("description",
true);
UpdatePreOpPlugin.addAttributeToRemove(attrType);
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
Entry e = DirectoryServer.getEntry(DN.decode("ou=People,o=test"));
List<Attribute> attrList = e.getAttribute(attrType);
assertNull(attrList);
UpdatePreOpPlugin.reset();
}
/**
* Invokes methods to retrieve members of an add operation after it has
* completed.
*
* @param addOperation The add operation to examine. It should have
* completed successfully.
*/
private void retrieveCompletedOperationElements(AddOperation addOperation)
{
assertTrue(addOperation.getProcessingStartTime() > 0);
assertTrue(addOperation.getProcessingStopTime() >=
addOperation.getProcessingStartTime());
assertTrue(addOperation.getProcessingTime() >= 0);
assertNotNull(addOperation.getResponseLogElements());
long changeNumber = addOperation.getChangeNumber();
addOperation.setChangeNumber(changeNumber);
}
/**
* Tests an internal add operation that should be successful using raw
* arguments.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessRaw()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(ByteString.valueOf("ou=People,o=test"), attrs);
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
}
/**
* Tests an internal add operation that should be successful using processed
* arguments.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessProcessed()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
}
/**
* Tests an internal add operation that fails because it contains a malformed
* DN.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureMalformedDN()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(ByteString.valueOf("invalid"), attrs);
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests an internal add operation that fails because it contains the DN of
* an entry that already exists.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureAlreadyExists()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organization"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("test"));
attrs.add(new LDAPAttribute("o", values));
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(ByteString.valueOf("o=test"), attrs);
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests an internal add operation that fails because it is a suffix that
* doesn't exist.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureNoSuchSuffix()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organization"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("undefined"));
attrs.add(new LDAPAttribute("o", values));
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(ByteString.valueOf("o=undefined"), attrs);
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests an internal add operation that fails because it is below a suffix
* that doesn't exist.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureNoSuchSuffixParent()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(ByteString.valueOf("ou=People,o=undefined"), attrs);
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests an internal add operation that fails because its parent doesn't
* exist.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureNoSuchParent()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(ByteString.valueOf("ou=People,o=missing,o=test"),
attrs);
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests an external add operation that fails because it contains an attribute
* that is marked no-user-modification.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testExternalAddFailureNoUserModification()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
LDAPReader r = new 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);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("cn=Directory Manager"));
attrs.add(new LDAPAttribute("creatorsName", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("20060101000000Z"));
attrs.add(new LDAPAttribute("createTimestamp", values));
long addRequests = ldapStatistics.getAddRequests();
long addResponses = ldapStatistics.getAddResponses();
AddRequestProtocolOp addRequest =
new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
attrs);
message = new LDAPMessage(2, addRequest);
w.writeMessage(message);
message = r.readMessage();
AddResponseProtocolOp addResponse =
message.getAddResponseProtocolOp();
assertFalse(addResponse.getResultCode() == 0);
assertEquals(ldapStatistics.getAddRequests(), addRequests+1);
waitForAddResponsesStat(addResponses+1);
try
{
s.close();
} catch (Exception e) {}
}
/**
* Tests an internal add operation that fails because it has an undefined
* objectclass.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureUndefinedObjectClass()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("undefined"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(ByteString.valueOf("ou=People,o=test"),
attrs);
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests a successful internal add operation that contains a user-modifiable
* operational attribute.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessfulWithOperationalAttribute()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: test.user",
"givenName: Test",
"sn: User",
"cn: Test User",
"userPassword: password",
"ds-pwp-password-policy-dn: cn=Clear UserPassword Policy," +
"cn=Password Policies,cn=config");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
}
/**
* Tests a successful internal add operation that contains an attribute with
* multiple values where the values are spread throughout the entry.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessfulDisjointAttribute()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("foo"));
attrs.add(new LDAPAttribute("description", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("bar"));
attrs.add(new LDAPAttribute("description", values));
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(ByteString.valueOf("ou=People,o=test"),
attrs);
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
}
/**
* Tests a successful internal add operation that contains raw attributes with
* options.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessfulWithRawAttributeOptions()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("foo"));
attrs.add(new LDAPAttribute("description", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("foo"));
attrs.add(new LDAPAttribute("description;lang-en-us", values));
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(ByteString.valueOf("ou=People,o=test"),
attrs);
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
}
/**
* Tests a successful internal add operation that contains raw attributes with
* options and an attribute that doesn't have any values without options.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessfulWithRawAttributeOptionsOnlyOptions()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("foo"));
attrs.add(new LDAPAttribute("description;lang-en-us", values));
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(ByteString.valueOf("ou=People,o=test"),
attrs);
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
}
/**
* Tests a successful internal add operation that contains attributes with
* options.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessfulWithAttributeOptions()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: test.user",
"uid;lang-en-us: test.user",
"givenName: Test",
"givenName;lang-en-us: Test",
"sn: User",
"sn;lang-en-us: User",
"cn: Test User",
"cn;lang-en-us: Test User",
"userPassword: password");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
}
/**
* Tests an internal add operation that fails because it attempts to add the
* root DSE.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureRootDSE()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("ds-root-dse"));
values.add(ByteString.valueOf("extensibleObject"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("Root DSE"));
attrs.add(new LDAPAttribute("cn", values));
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(ByteString.empty(), attrs);
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests a successful internal add operation that is missing RDN attributes.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessfulWithMissingRDNAttributes()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
Entry e = DirectoryServer.getEntry(DN.decode("ou=People,o=test"));
List<Attribute> attrList = e.getAttribute("ou");
assertNotNull(attrList);
}
/**
* Tests a failed internal add operation that is missing RDN attributes.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureWithMissingRDNAttributes()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
DirectoryServer.setAddMissingRDNAttributes(false);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
DirectoryServer.setAddMissingRDNAttributes(true);
}
/**
* Tests a successful internal add operation that is missing an objectclass
* in the hierarchical chain.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessfulWithMissingParentObjectClass()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: inetOrgPerson",
"uid: test.user",
"givenName: Test",
"sn: User",
"cn: Test User",
"userPassword: password");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
Entry e = DirectoryServer.getEntry(DN.decode("uid=test.user,o=test"));
List<Attribute> attrList =
e.getAttribute(DirectoryServer.getObjectClassAttributeType());
assertNotNull(attrList);
boolean found = false;
for (Attribute a : attrList)
{
for (AttributeValue v : a)
{
if (v.getValue().toString().equalsIgnoreCase("top"))
{
found = true;
break;
}
}
}
assertTrue(found);
}
/**
* Tests a failed internal add operation that doesn't have any objectclasses.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureNoObjectClasses()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests a failed internal add operation that only has an abstract
* objectclass.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureOnlyAbstractObjectClass()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests a failed internal add operation that doesn't have any structural
* objectclass (only abstract and auxiliary).
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureNoStructuralObjectClass()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: extensibleObject",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests a failed internal add operation that has multiple structural
* objectclasses.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureMultipleStructuralObjectClasses()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"objectClass: person",
"ou: People",
"cn: Test User",
"sn: User");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests a failed internal add operation that is missing a required attribute.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureMissingRequiredAttribute()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: test.user",
"givenName: Test",
"sn: User",
"userPassword: password"); // Missing cn
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests a failed internal add operation that is missing a required attribute
* but has the extensibleObject objectClass (which shouldn't change anything).
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureMissingRequiredAttributeExtensibleObject()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"objectClass: extensibleObject",
"uid: test.user",
"givenName: Test",
"sn: User",
"userPassword: password"); // Missing cn
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests a failed internal add operation that contains an attribute not
* allowed by any objectclass.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureDisallowedAttribute()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: test.user",
"givenName: Test",
"sn: User",
"cn: Test User",
"userPassword: password",
"dc: Not allowed by inetOrgPerson");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests a successful internal add operation that contains an attribute not
* allowed by any standard objectclass in the entry but is allowed by
* extensibleObject.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessfulDisallowedAttributeExtensibleObject()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"objectClass: extensibleObject",
"uid: test.user",
"givenName: Test",
"sn: User",
"cn: Test User",
"userPassword: password",
"dc: Not allowed by inetOrgPerson but allowed by extensibleObject");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
}
/**
* Tests the behavior of the server when attempting to perform an add \
* operation with an entry containing an attribute with zero values.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureEmptyAttribute()
throws Exception
{
TestCaseUtils.initializeTestBackend(false);
Entry entry = TestCaseUtils.makeEntry(
"dn: o=test",
"objectClass: top",
"objectClass: organization",
"o: test");
Map<AttributeType,List<Attribute>> userAttrs = entry.getUserAttributes();
AttributeType attrType = DirectoryServer.getAttributeType("description");
ArrayList<Attribute> attrList = new ArrayList<Attribute>();
attrList.add(Attributes.empty(attrType));
userAttrs.put(attrType, attrList);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(), userAttrs,
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
}
/**
* Tests a failed internal add operation with the server in complete read-only
* mode.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureServerCompletelyReadOnly()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: test.user",
"givenName: Test",
"sn: User",
"cn: Test User",
"userPassword: password");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DirectoryServer.setWritabilityMode(WritabilityMode.DISABLED);
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests a successful internal add operation with the server in read-only mode
* for external operations but allowed for internal operations.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessServerExternallyReadOnly()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: test.user",
"givenName: Test",
"sn: User",
"cn: Test User",
"userPassword: password");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
DirectoryServer.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests a failed external add operation with the server in read-only mode
* for external operations but allowed for internal operations.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testExternalAddFailureServerExternallyReadOnly()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
LDAPReader r = new 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);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
DirectoryServer.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
long addRequests = ldapStatistics.getAddRequests();
long addResponses = ldapStatistics.getAddResponses();
AddRequestProtocolOp addRequest =
new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
attrs);
message = new LDAPMessage(2, addRequest);
w.writeMessage(message);
message = r.readMessage();
AddResponseProtocolOp addResponse =
message.getAddResponseProtocolOp();
assertFalse(addResponse.getResultCode() == 0);
assertEquals(ldapStatistics.getAddRequests(), addRequests+1);
waitForAddResponsesStat(addResponses+1);
try
{
s.close();
} catch (Exception e) {}
DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests a failed internal add operation with the backend in complete
* read-only mode.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddFailureBackendCompletelyReadOnly()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: test.user",
"givenName: Test",
"sn: User",
"cn: Test User",
"userPassword: password");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
b.setWritabilityMode(WritabilityMode.DISABLED);
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
b.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests a successful internal add operation with the backend in read-only
* mode for external operations but allowed for internal operations.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testInternalAddSuccessBackendExternallyReadOnly()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: uid=test.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: test.user",
"givenName: Test",
"sn: User",
"cn: Test User",
"userPassword: password");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
b.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
b.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests a failed external add operation with the backend in read-only mode
* for external operations but allowed for internal operations.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testExternalAddFailureBackendExternallyReadOnly()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
LDAPReader r = new 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);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
b.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
long addRequests = ldapStatistics.getAddRequests();
long addResponses = ldapStatistics.getAddResponses();
AddRequestProtocolOp addRequest =
new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
attrs);
message = new LDAPMessage(2, addRequest);
w.writeMessage(message);
message = r.readMessage();
AddResponseProtocolOp addResponse =
message.getAddResponseProtocolOp();
assertFalse(addResponse.getResultCode() == 0);
assertEquals(ldapStatistics.getAddRequests(), addRequests+1);
waitForAddResponsesStat(addResponses+1);
try
{
s.close();
} catch (Exception e) {}
b.setWritabilityMode(WritabilityMode.ENABLED);
}
/**
* Tests to ensure that any registered add notification listeners are invoked
* for a successful add 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);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(addOperation);
assertEquals(changeListener.getAddCount(), 1);
DirectoryServer.deregisterChangeNotificationListener(changeListener);
}
/**
* Tests to ensure that any registered add notification listeners are not
* invoked for a failed add 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);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,ou=nonexistent,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertFalse(addOperation.getResultCode() == ResultCode.SUCCESS);
assertEquals(changeListener.getAddCount(), 0);
DirectoryServer.deregisterChangeNotificationListener(changeListener);
}
/**
* Tests an add operation that gets canceled before startup.
*
* @throws Exception If an unexpected probem occurs.
*/
@Test()
public void testCancelBeforeStartup()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperationBasis addOperation =
new AddOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
CancelRequest cancelRequest = new CancelRequest(false,
Message.raw("testCancelBeforeStartup"));
addOperation.abort(cancelRequest);
addOperation.run();
assertEquals(addOperation.getResultCode(), ResultCode.CANCELED);
}
/**
* Tests an add operation that gets canceled before startup.
*
* @throws Exception If an unexpected probem occurs.
*/
@Test()
public void testCancelAfterOperation()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperationBasis addOperation =
new AddOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
addOperation.run();
CancelRequest cancelRequest = new CancelRequest(false,
Message.raw("testCancelAfterOperation"));
CancelResult cancelResult = addOperation.cancel(cancelRequest);
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertEquals(cancelResult.getResultCode(), ResultCode.TOO_LATE);
}
/**
* Tests an add 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("ou=People,o=test"));
try
{
Entry entry = TestCaseUtils.makeEntry(
"dn: ou=People,o=test",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
AddOperation addOperation =
conn.processAdd(entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.BUSY);
}
finally
{
LockManager.unlock(DN.decode("ou=People,o=test"), entryLock);
}
}
/**
* Tests an add operation that should be disconnected in a pre-parse plugin.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDisconnectInPreParseAdd()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
LDAPReader r = new 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);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
AddRequestProtocolOp addRequest =
new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
attrs);
message = new LDAPMessage(2, addRequest,
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 an add operation that should be disconnected in a pre-operation
* plugin.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDisconnectInPreOperationAdd()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
LDAPReader r = new 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);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
AddRequestProtocolOp addRequest =
new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
attrs);
message = new LDAPMessage(2, addRequest,
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 an add operation that should be disconnected in a post-operation
* plugin.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDisconnectInPostOperationAdd()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
LDAPReader r = new 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);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
AddRequestProtocolOp addRequest =
new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
attrs);
message = new LDAPMessage(2, addRequest,
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 an add operation that should be disconnected in a post-response
* plugin.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDisconnectInPostResponseAdd()
throws Exception
{
TestCaseUtils.initializeTestBackend(true);
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
LDAPReader r = new 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);
ArrayList<RawAttribute> attrs = new ArrayList<RawAttribute>();
ArrayList<ByteString> values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("top"));
values.add(ByteString.valueOf("organizationalUnit"));
attrs.add(new LDAPAttribute("objectClass", values));
values = new ArrayList<ByteString>();
values.add(ByteString.valueOf("People"));
attrs.add(new LDAPAttribute("ou", values));
AddRequestProtocolOp addRequest =
new AddRequestProtocolOp(ByteString.valueOf("ou=People,o=test"),
attrs);
message = new LDAPMessage(2, addRequest,
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_ADD_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 " +
"testDisconnectInPostResponseAdd");
}
}
try
{
s.close();
} catch (Exception e) {}
}
/**
* Tests an add operation that attempts to add an entry with a user attribute
* marked OBSOLETE in the server schema.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testAddObsoleteUserAttribute()
throws Exception
{
TestCaseUtils.initializeTestBackend(false);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: attributeTypes",
"attributeTypes: ( testaddobsoleteuserattribute-oid " +
"NAME 'testAddObsoleteUserAttribute' OBSOLETE " +
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE " +
"X-ORGIN 'SchemaBackendTestCase' )");
String attrName = "testaddobsoleteuserattribute";
assertFalse(DirectoryServer.getSchema().hasAttributeType(attrName));
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
assertTrue(DirectoryServer.getSchema().hasAttributeType(attrName));
path = TestCaseUtils.createTempFile(
"dn: o=test",
"changetype: add",
"objectClass: top",
"objectClass: organization",
"objectClass: extensibleObject",
"o: test",
"testAddObsoleteUserAttribute: foo");
args = new String[]
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertFalse(LDAPModify.mainModify(args, false, null, null) == 0);
}
/**
* Tests an add operation that attempts to add an entry with an operational
* attribute marked OBSOLETE in the server schema.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testAddObsoleteOperationalAttribute()
throws Exception
{
TestCaseUtils.initializeTestBackend(false);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: attributeTypes",
"attributeTypes: ( testaddobsoleteoperationalattribute-oid " +
"NAME 'testAddObsoleteOperationalAttribute' OBSOLETE " +
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE " +
"USAGE directoryOperation X-ORGIN 'SchemaBackendTestCase' )");
String attrName = "testaddobsoleteoperationalattribute";
assertFalse(DirectoryServer.getSchema().hasAttributeType(attrName));
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
assertTrue(DirectoryServer.getSchema().hasAttributeType(attrName));
path = TestCaseUtils.createTempFile(
"dn: o=test",
"changetype: add",
"objectClass: top",
"objectClass: organization",
"objectClass: extensibleObject",
"o: test",
"testAddObsoleteOperationalAttribute: foo");
args = new String[]
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertFalse(LDAPModify.mainModify(args, false, null, null) == 0);
}
/**
* Tests an add operation that attempts to add an entry with an auxiliary
* objectclass marked OBSOLETE in the server schema.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testAddObsoleteObjectClass()
throws Exception
{
TestCaseUtils.initializeTestBackend(false);
String path = TestCaseUtils.createTempFile(
"dn: cn=schema",
"changetype: modify",
"add: objectClasses",
"objectClasses: ( testaddobsoleteobjectclass-oid " +
"NAME 'testAddObsoleteObjectClass' OBSOLETE AUXILIARY " +
"MAY description X-ORGIN 'SchemaBackendTestCase' )");
String ocName = "testaddobsoleteobjectclass";
assertFalse(DirectoryServer.getSchema().hasObjectClass(ocName));
String[] args =
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
assertTrue(DirectoryServer.getSchema().hasObjectClass(ocName));
path = TestCaseUtils.createTempFile(
"dn: o=test",
"changetype: add",
"objectClass: top",
"objectClass: organization",
"objectClass: testAddObsoleteObjectClass",
"o: test");
args = new String[]
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
assertFalse(LDAPModify.mainModify(args, false, null, null) == 0);
}
/**
* Tests the behavior of the server when short-circuiting out of an add
* 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(false);
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
List<Control> controls =
ShortCircuitPlugin.createShortCircuitControlList(0, "PreParse");
ArrayList<ByteString> ocValues = new ArrayList<ByteString>();
ocValues.add(ByteString.valueOf("top"));
ocValues.add(ByteString.valueOf("organization"));
ArrayList<RawAttribute> rawAttrs = new ArrayList<RawAttribute>();
rawAttrs.add(RawAttribute.create("objectClass", ocValues));
rawAttrs.add(RawAttribute.create("o", "test"));
AddOperationBasis addOperation =
new AddOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(),
controls, ByteString.valueOf("o=test"), rawAttrs);
addOperation.run();
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertFalse(DirectoryServer.entryExists(DN.decode("o=test")));
}
}