/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2006-2011 Sun Microsystems, Inc. * Portions Copyright 2011-2014 ForgeRock AS */ package org.opends.server.core; import java.net.Socket; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.locks.Lock; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.opendj.ldap.ByteString; import org.forgerock.opendj.ldap.SearchScope; 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.internal.InternalSearchOperation; import org.opends.server.protocols.ldap.*; import org.opends.server.tools.LDAPModify; import org.opends.server.tools.LDAPWriter; import org.opends.server.types.*; import org.opends.server.util.Base64; import org.opends.server.util.ServerConstants; import org.opends.server.util.StaticUtils; import org.opends.server.workflowelement.localbackend.LocalBackendModifyOperation; import org.testng.annotations.*; import static org.opends.server.TestCaseUtils.*; import static org.opends.server.protocols.ldap.LDAPConstants.*; import static org.testng.Assert.*; /** * A set of test cases for modify operations */ @SuppressWarnings("javadoc") public class ModifyOperationTestCase extends OperationTestCase { @BeforeClass public void restartServer() throws Exception { TestCaseUtils.restartServer(); } // Some of the tests disable the backends, so we reenable them here. @AfterMethod(alwaysRun=true) public void reenableBackend() throws DirectoryException { Object[][] backendBaseDNs = getBaseDNs(); for (Object[] backendBaseDN2 : backendBaseDNs) { String backendBaseDN = backendBaseDN2[0].toString(); Backend b = DirectoryServer.getBackend(DN.valueOf(backendBaseDN)); b.setWritabilityMode(WritabilityMode.ENABLED); } } /** * Retrieves a set of modify operations that may be used for testing. * * @return A set of modify operations that may be used for testing. * * @throws Exception If an unexpected problem occurs. */ @DataProvider(name = "modifyOperations") public Object[][] getModifyOperations() throws Exception { List opList = new ArrayList(); List noControls = new ArrayList(); List ldapMods = new ArrayList(); LDAPAttribute ldapAttr = new LDAPAttribute("description", "foo"); ldapMods.add(add(ldapAttr)); opList.add(newModifyOperation(null, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(null, ByteString.valueOf("o=test"), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.valueOf("o=test"), ldapMods)); ldapMods = new ArrayList(); ldapMods.add(delete(ldapAttr)); opList.add(newModifyOperation(null, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(null, ByteString.valueOf("o=test"), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.valueOf("o=test"), ldapMods)); ldapMods = new ArrayList(); ldapMods.add(replace(ldapAttr)); opList.add(newModifyOperation(null, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(null, ByteString.valueOf("o=test"), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.valueOf("o=test"), ldapMods)); ldapMods = new ArrayList(); ArrayList values2 = new ArrayList(); values2.add(ByteString.valueOf("bar")); LDAPAttribute ldapAttr2 = new LDAPAttribute("description", values2); ldapMods.add(delete(ldapAttr)); ldapMods.add(add(ldapAttr2)); opList.add(newModifyOperation(null, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(null, ByteString.valueOf("o=test"), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.valueOf("o=test"), ldapMods)); ldapMods = new ArrayList(); ldapAttr2 = new LDAPAttribute("cn", values2); ldapMods.add(replace(ldapAttr)); ldapMods.add(replace(ldapAttr2)); opList.add(newModifyOperation(null, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(null, ByteString.valueOf("o=test"), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.valueOf("o=test"), ldapMods)); List mods = new ArrayList(); mods.add(new Modification(ModificationType.ADD, Attributes.create("description", "foo"))); opList.add(newModifyOperation(null, DN.rootDN(), mods)); opList.add(newModifyOperation(noControls, DN.rootDN(), mods)); opList.add(newModifyOperation(null, DN.valueOf("o=test"), mods)); opList.add(newModifyOperation(noControls, DN.valueOf("o=test"), mods)); mods = new ArrayList(); mods.add(new Modification(ModificationType.DELETE, Attributes.create("description", "foo"))); opList.add(newModifyOperation(null, DN.rootDN(), mods)); opList.add(newModifyOperation(noControls, DN.rootDN(), mods)); opList.add(newModifyOperation(null, DN.valueOf("o=test"), mods)); opList.add(newModifyOperation(noControls, DN.valueOf("o=test"), mods)); mods = new ArrayList(); mods.add(new Modification(ModificationType.REPLACE, Attributes.create("description", "foo"))); opList.add(newModifyOperation(null, DN.rootDN(), mods)); opList.add(newModifyOperation(noControls, DN.rootDN(), mods)); opList.add(newModifyOperation(null, DN.valueOf("o=test"), mods)); opList.add(newModifyOperation(noControls, DN.valueOf("o=test"), mods)); mods = new ArrayList(); mods.add(new Modification(ModificationType.DELETE, Attributes.create("description", "foo"))); mods.add(new Modification(ModificationType.ADD, Attributes.create("description", "bar"))); opList.add(newModifyOperation(null, DN.rootDN(), mods)); opList.add(newModifyOperation(noControls, DN.rootDN(), mods)); opList.add(newModifyOperation(null, DN.valueOf("o=test"), mods)); opList.add(newModifyOperation(noControls, DN.valueOf("o=test"), mods)); mods = new ArrayList(); mods.add(new Modification(ModificationType.REPLACE, Attributes.create("description", "foo"))); mods.add(new Modification(ModificationType.REPLACE, Attributes.create("cn", "bar"))); opList.add(newModifyOperation(null, DN.rootDN(), mods)); opList.add(newModifyOperation(noControls, DN.rootDN(), mods)); opList.add(newModifyOperation(null, DN.valueOf("o=test"), mods)); opList.add(newModifyOperation(noControls, DN.valueOf("o=test"), mods)); Object[][] objArray = new Object[opList.size()][1]; for (int i=0; i < objArray.length; i++) { objArray[i][0] = opList.get(i); } return objArray; } private ModifyOperation newModifyOperation(List requestControls, DN entryDn, List modifications) { return new ModifyOperationBasis( InternalClientConnection.getRootConnection(), InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), requestControls, entryDn, modifications); } private ModifyOperation newModifyOperation(List requestControls, ByteString rawEntryDn, List rawModifications) { return new ModifyOperationBasis( InternalClientConnection.getRootConnection(), InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), requestControls, rawEntryDn, rawModifications); } @DataProvider(name = "baseDNs") public Object[][] getBaseDNs() { return new Object[][] { { "o=test"} }; } @BeforeMethod public void clearTestBackend() throws Exception { TestCaseUtils.initializeTestBackend(true); } /** * {@inheritDoc} */ @Override() protected Operation[] createTestOperations() throws Exception { Object[][] objs = getModifyOperations(); Operation[] ops = new Operation[objs.length]; for (int i=0; i < objs.length; i++) { ops[i] = (Operation) objs[i][0]; } return ops; } /** * Tests the getRawEntryDN and setRawEntryDN * methods. * * @param modifyOperation The modify operation to be tested. */ @Test(dataProvider = "modifyOperations") public void testGetAndSetRawEntryDN(ModifyOperation modifyOperation) { ByteString originalDN = modifyOperation.getRawEntryDN(); assertNotNull(originalDN); modifyOperation.setRawEntryDN(ByteString.valueOf("uid=test,o=test")); assertNotNull(modifyOperation.getRawEntryDN()); assertEquals(modifyOperation.getRawEntryDN(), ByteString.valueOf("uid=test,o=test")); modifyOperation.setRawEntryDN(originalDN); assertNotNull(modifyOperation.getRawEntryDN()); assertEquals(modifyOperation.getRawEntryDN(), originalDN); } /** * Tests the getEntryDN method that should decode * the raw entry dn and return a non-null DN. */ @Test() public void testGetEntryDNInitiallyNull() { LDAPAttribute attr = newLDAPAttribute("description", "foo"); List mods = new ArrayList(); mods.add(replace(attr)); ModifyOperation modifyOperation = newModifyOperation(null, ByteString.empty(), mods); assertNotNull(modifyOperation.getEntryDN()); } private LDAPAttribute newLDAPAttribute(String sttributeType, String... valueStrings) { ArrayList values = new ArrayList(); for (String valueStr : valueStrings) { values.add(ByteString.valueOf(valueStr)); } return new LDAPAttribute(sttributeType, values); } /** * Tests the getEntryDN 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 { List mods = new ArrayList(); mods.add(new Modification(ModificationType.REPLACE, Attributes.create("description", "foo"))); ModifyOperation modifyOperation = newModifyOperation(null, DN.rootDN(), mods); assertNotNull(modifyOperation.getEntryDN()); } /** * Tests the getEntryDN method for the case in which we expect * the DN to be initially non-null, then is null after the raw DN is * changed, but becomes non-null after the call to getEntryDN. * * @throws Exception If an unexpected problem occurs. */ @Test() public void testGetEntryDNNonNullChangedToNull() throws Exception { List mods = new ArrayList(); mods.add(new Modification(ModificationType.REPLACE, Attributes.create("description", "foo"))); ModifyOperation modifyOperation = newModifyOperation(null, DN.rootDN(), mods); assertNotNull(modifyOperation.getEntryDN()); modifyOperation.setRawEntryDN(ByteString.valueOf("ou=Users,o=test")); assertNotNull(modifyOperation.getEntryDN()); } /** * Tests the getRawModifications, * addRawModification, and setRawModifications * methods. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "modifyOperations") public void testGetAndSetRawModifications(ModifyOperation modifyOperation) throws Exception { List rawMods = modifyOperation.getRawModifications(); List clonedMods = new ArrayList(rawMods); modifyOperation.setRawModifications(clonedMods); LDAPAttribute attr = newLDAPAttribute("test", "test"); modifyOperation.addRawModification(replace(attr)); assertEquals(modifyOperation.getRawModifications().size(), (rawMods.size() + 1)); modifyOperation.setRawModifications(rawMods); assertEquals(modifyOperation.getRawModifications().size(), rawMods.size()); } /** * Invokes methods to retrieve members of a modify operation after it has * completed successfully. * * @param modifyOperation The modify operation to examine. It should have * completed successfully. */ private void retrieveSuccessfulOperationElements( ModifyOperation modifyOperation) { assertTrue(modifyOperation.getProcessingStartTime() > 0); assertTrue(modifyOperation.getProcessingStopTime() >= modifyOperation.getProcessingStartTime()); assertTrue(modifyOperation.getProcessingTime() >= 0); List localOps = (List) (modifyOperation.getAttachment(Operation.LOCALBACKENDOPERATIONS)); assertNotNull(localOps); for (LocalBackendModifyOperation curOp : localOps) { curOp.getNewPasswords(); curOp.getCurrentPasswords(); assertNotNull(curOp.getCurrentEntry()); assertNotNull(curOp.getModifiedEntry()); } long changeNumber = modifyOperation.getChangeNumber(); modifyOperation.setChangeNumber(changeNumber); } /** * Invokes methods to retrieve members of a modify operation after it has * completed unsuccessfully. * * @param modifyOperation The modify operation to examine. It should have * completed failed. */ private void retrieveFailedOperationElements( ModifyOperation modifyOperation) { assertTrue(modifyOperation.getProcessingStartTime() > 0); assertTrue(modifyOperation.getProcessingStopTime() >= modifyOperation.getProcessingStartTime()); assertTrue(modifyOperation.getProcessingTime() >= 0); long changeNumber = modifyOperation.getChangeNumber(); modifyOperation.setChangeNumber(changeNumber); } /** * Tests the getModifications and addModification * methods. * * @throws Exception If an unexpected problem occurs. */ @Test() public void testGetAndAddModifications() throws Exception { Entry e = DirectoryServer.getEntry(DN.valueOf("o=test")); assertNull(e.getAttribute(DirectoryServer.getAttributeType("description", true))); UpdatePreOpPlugin.reset(); UpdatePreOpPlugin.addModification( new Modification(ModificationType.REPLACE, Attributes.create("description", "foo"))); InternalClientConnection conn = InternalClientConnection.getRootConnection(); List mods = new ArrayList(); mods.add(new Modification(ModificationType.REPLACE, Attributes.create("l", "Austin"))); ModifyOperation modifyOperation = conn.processModify(DN.valueOf("o=test"), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); e = DirectoryServer.getEntry(DN.valueOf("o=test")); assertNotNull(e.getAttribute(DirectoryServer.getAttributeType("description", true))); UpdatePreOpPlugin.reset(); } /** * Tests to ensure that a modify attempt fails if an invalid DN is provided. */ @Test() public void testFailInvalidDN() { LDAPAttribute attr = newLDAPAttribute("description", "foo"); ModifyOperation modifyOperation = processModify("invaliddn", replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if the target DN is a suffix * that doesn't exist. */ @Test() public void testFailNoSuchSuffix() { LDAPAttribute attr = newLDAPAttribute("description", "foo"); ModifyOperation modifyOperation = processModify("o=nonexistent", replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if the target DN doesn't have a * parent. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailNoSuchParent(String baseDN) throws Exception { LDAPAttribute attr = newLDAPAttribute("description", "foo"); ModifyOperation modifyOperation = processModify("cn=test,ou=nosuchparent," + baseDN, replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if the target entry doesn't * exist. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailNoSuchEntry(String baseDN) throws Exception { LDAPAttribute attr = newLDAPAttribute("description", "foo"); ModifyOperation modifyOperation = processModify("cn=nosuchentry," + baseDN, replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if the modification doesn't * contain any changes. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailNoModifications(String baseDN) throws Exception { ModifyOperation modifyOperation = processModify(baseDN); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that adds a new attribute to an * entry. * * @throws Exception If an unexpected problem occurs. */ @Test() public void testSuccessAddAttribute() throws Exception { Entry e = DirectoryServer.getEntry(DN.valueOf("o=test")); assertNull(e.getAttribute(DirectoryServer.getAttributeType("description", true))); LDAPAttribute attr = newLDAPAttribute("description", "foo"); ModifyOperation modifyOperation = processModify("o=test", replace(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); e = DirectoryServer.getEntry(DN.valueOf("o=test")); assertNotNull(e.getAttribute(DirectoryServer.getAttributeType("description", true))); } /** * Tests the ability to perform a modification that adds a new value to an * existing attribute. * * @throws Exception If an unexpected problem occurs. */ @Test() public void testSuccessAddAttributeValue() throws Exception { Entry e = DirectoryServer.getEntry(DN.valueOf("o=test")); List attrList = e.getAttribute(DirectoryServer.getAttributeType("o", true)); assertEquals(countValues(attrList), 1); LDAPAttribute attr = newLDAPAttribute("o", "test2"); ModifyOperation modifyOperation = processModify("o=test", add(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); e = DirectoryServer.getEntry(DN.valueOf("o=test")); attrList = e.getAttribute(DirectoryServer.getAttributeType("o", true)); assertEquals(countValues(attrList), 2); } /** * Tests the ability to perform a modification that adds a new attribute with * options to an entry. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessAddAttributeWithOptions(String baseDN) throws Exception { Entry e = DirectoryServer.getEntry(DN.valueOf(baseDN)); List attrList = e.getAttribute(DirectoryServer.getAttributeType("o", true)); assertEquals(countValues(attrList), 1); LDAPAttribute attr = newLDAPAttribute("o;lang-en-us", "test"); ModifyOperation modifyOperation = processModify(baseDN, add(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); e = DirectoryServer.getEntry(DN.valueOf(baseDN)); attrList = e.getAttribute(DirectoryServer.getAttributeType("o", true)); assertEquals(countValues(attrList), 2); } private int countValues(List attrList) { int count = 0; for (Attribute a : attrList) { count += a.size(); } return count; } /** * Tests to ensure that a modify attempt fails if an attempt is made to add a * second value to a single-valued attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailAddToSingleValuedAttribute(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("displayName", "foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to add a * second value to a single-valued operational attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailAddToSingleValuedOperationalAttribute(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "ds-pwp-account-disabled: true"); LDAPAttribute attr = newLDAPAttribute("ds-pwp-account-disabled", "false"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * replace a single-valued attribute with multiple values. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailReplaceSingleValuedWithMultipleValues(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("displayName", "foo", "bar"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * replace a single-valued operational attribute with multiple values. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailReplaceSingleValuedOperationalAttrWithMultipleValues( String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("ds-pwp-account-disabled", "true", "false"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } private LDAPModification replace(LDAPAttribute attr) { return new LDAPModification(ModificationType.REPLACE, attr); } private LDAPModification add(LDAPAttribute attr) { return new LDAPModification(ModificationType.ADD, attr); } private LDAPModification delete(LDAPAttribute attr) { return new LDAPModification(ModificationType.DELETE, attr); } private LDAPModification increment(LDAPAttribute attr) { return new LDAPModification(ModificationType.INCREMENT, attr); } private ModifyOperation processModify(String entryDN, List mods) { InternalClientConnection conn = InternalClientConnection.getRootConnection(); return conn.processModify(ByteString.valueOf(entryDN), mods); } private ModifyOperation processModify(String entryDN, RawModification... mods) { InternalClientConnection conn = InternalClientConnection.getRootConnection(); return conn.processModify(ByteString.valueOf(entryDN), Arrays.asList(mods)); } private ModifyOperation processModify(String entryDN, List mods, List requestControls) { InternalClientConnection conn = InternalClientConnection.getRootConnection(); return conn.processModify(ByteString.valueOf(entryDN), mods, requestControls); } private void processAdd(String... entryLines) throws Exception { Entry entry = TestCaseUtils.makeEntry(entryLines); InternalClientConnection conn = InternalClientConnection.getRootConnection(); AddOperation addOperation = conn.processAdd(entry.getName(), entry.getObjectClasses(), entry .getUserAttributes(), entry.getOperationalAttributes()); assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); } /** * Tests to ensure that a modify attempt fails if an attempt is made to add a * value that matches one that already exists. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailAddDuplicateValue(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("givenName", "Test"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * replace an attribute with a set of values that contains a duplicate. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailReplaceWithDuplicates(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("description", "Foo", "Foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * replace with a value that violates the attribute syntax. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailReplaceWithSyntaxViolation(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "manager: cn=boss," + baseDN); LDAPAttribute attr = newLDAPAttribute("manager", "invaliddn"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to add a * value that violates the attribute syntax. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailAddSyntaxViolation(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("manager", "invaliddn"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to add an * attribute that is not allowed by any objectclass. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailAddDisallowedAttribute(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("dc", "foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.OBJECTCLASS_VIOLATION); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt succeeds if an attempt is made to add * an attribute that is not allowed by any objectclass but the * extensibleObject objectclass is also added. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessAddDisallowedAttributeWithExtensibleObject( String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("dc", "foo"); attr = newLDAPAttribute("objectClass", "extensibleObject"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * replace the RDN attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailReplaceRDNAttribute(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("uid", "foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * remove the RDN attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailRemoveRDNAttribute(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = new LDAPAttribute("uid"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * remove the RDN attribute value. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailRemoveRDNValue(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("uid", "test.user"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * replace an RDN attribute in a multivalued RDN. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailReplaceOneOfMultipleRDNAttributes(String baseDN) throws Exception { processAdd( "dn: givenName=Test+sn=User," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("givenName", "Foo"); ModifyOperation modifyOperation = processModify("givenName=Test,sn=User," + baseDN, replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * remove an RDN attribute value from a multivalued RDN. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailRemoveOneOfMultipleRDNValues(String baseDN) throws Exception { processAdd( "dn: givenName=Test+sn=User," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = new LDAPAttribute("givenName"); ModifyOperation modifyOperation = processModify("givenName=Test,sn=User," + baseDN, delete(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that removes a complete * attribute from an entry. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessRemoveCompleteAttribute(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = new LDAPAttribute("displayName"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that removes one of multiple * values from an entry. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessRemoveOneOfManyValues(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "mail: bar"); LDAPAttribute attr = newLDAPAttribute("mail", "foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that removes the only value of * an existing attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessRemoveOnlyValue(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo"); LDAPAttribute attr = newLDAPAttribute("mail", "foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that removes all of multiple * values from an existing attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessRemoveAllOfManyValues(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "mail: bar"); LDAPAttribute attr = newLDAPAttribute("mail", "foo", "bar"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to remove * a required attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailRemoveRequiredAttribute(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = new LDAPAttribute("sn"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to remove * the only value for a required attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailRemoveRequiredAttributeValue(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("sn", "User"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that replaces an existing * attribute with something else. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessReplaceExistingWithNew(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo"); LDAPAttribute attr = newLDAPAttribute("description", "bar"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that replaces an existing * attribute with the same value. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessReplaceExistingWithSame(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo"); LDAPAttribute attr = newLDAPAttribute("uid", "test.user"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); InternalSearchOperation searchOperation = new InternalSearchOperation( InternalClientConnection.getRootConnection(), InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList(), ByteString.valueOf("uid=test.user," + baseDN), SearchScope.WHOLE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, Integer.MAX_VALUE, Integer.MAX_VALUE, false, LDAPFilter.decode("(uid=test.user)"), null, null); searchOperation.run(); assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS); assertEquals(searchOperation.getEntriesSent(), 1); assertEquals(searchOperation.getErrorMessage().length(), 0); } /** * Tests the ability to perform a modification that deletes a value then * adds the same value in a single operation. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessDeleteAndAddSameValue(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo"); LDAPAttribute attr = newLDAPAttribute("cn", "Test User"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr), add(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); InternalSearchOperation searchOperation = new InternalSearchOperation( InternalClientConnection.getRootConnection(), InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList(), ByteString.valueOf(baseDN), SearchScope.WHOLE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, Integer.MAX_VALUE, Integer.MAX_VALUE, false, LDAPFilter.decode("(cn=Test User)"), null, null); searchOperation.run(); assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS); assertEquals(searchOperation.getEntriesSent(), 1); assertEquals(searchOperation.getErrorMessage().length(), 0); } /** * Tests the ability to perform a modification that deletes one value of an * attribute containing two values, the values are the same but the attribute * options differ. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessDeleteAttributeWithOption(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "givenName;lang-de: X", "givenName;lang-fr: X", "displayName: Test User", "userPassword: password", "mail: foo"); LDAPAttribute attr = newLDAPAttribute("givenName;lang-fr", "X"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); InternalSearchOperation searchOperation = new InternalSearchOperation( InternalClientConnection.getRootConnection(), InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList(), ByteString.valueOf(baseDN), SearchScope.WHOLE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, Integer.MAX_VALUE, Integer.MAX_VALUE, false, LDAPFilter.decode("(givenName;lang-de=X)"), null, null); searchOperation.run(); assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS); assertEquals(searchOperation.getEntriesSent(), 1); assertEquals(searchOperation.getErrorMessage().length(), 0); } /** * Tests the ability to perform a modification that replaces an existing * attribute with nothing. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessReplaceExistingWithNothing(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo"); LDAPAttribute attr = new LDAPAttribute("description"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that replaces a nonexistent * attribute with nothing. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessReplaceNonExistingWithNothing(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = new LDAPAttribute("description"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that replaces a nonexistent * attribute with a new attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessReplaceNonExistingWithNew(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("description", "foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that removes the only existing * value and adds a new value. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessRemoveOnlyExistingAndAddNew(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo"); LDAPAttribute attr = newLDAPAttribute("mail", "foo"); LDAPAttribute attr2 = newLDAPAttribute("mail", "bar"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr), add(attr2)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that removes one of many values * and adds a new value. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessRemoveOneExistingAndAddNew(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "mail: bar"); LDAPAttribute attr = newLDAPAttribute("mail", "foo"); LDAPAttribute attr2 = new LDAPAttribute("mail", "baz"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr), add(attr2)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that removes one of many values * existing value and adds multiple new values. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessRemoveOneExistingAndAddMultipleNew(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo"); LDAPAttribute attr = newLDAPAttribute("mail", "foo"); LDAPAttribute attr2 = newLDAPAttribute("mail", "bar", "baz"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr), add(attr2)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to remove * a nonexistent attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailRemoveNonExistentAttribute(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "userPassword: password"); LDAPAttribute attr = new LDAPAttribute("displayName"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to remove * a nonexistent attribute value. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailRemoveNonExistentValue(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("displayName", "Foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to remove * all objectclasses from an entry. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailRemoveAllObjectClasses(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = new LDAPAttribute("objectClass"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * replace all objectclasses in an entry with nothing. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailReplaceObjectClassesWithNothing(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = new LDAPAttribute("objectClass"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to remove * the structural objectclass from an entry. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailRemoveStructuralObjectclass(String baseDN) throws Exception { processAdd( "dn: ou=People," + baseDN, "objectClass: top", "objectClass: organizationalUnit", "objectClass: extensibleObject", "ou: People"); LDAPAttribute attr = newLDAPAttribute("objectClass", "organizationalUnit"); ModifyOperation modifyOperation = processModify("ou=People," + baseDN, delete(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to add a * second structural objectclass. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailAddSecondStructuralObjectClass(String baseDN) throws Exception { processAdd( "dn: ou=People," + baseDN, "objectClass: top", "objectClass: organizationalUnit", "objectClass: extensibleObject", "ou: People"); LDAPAttribute attr = newLDAPAttribute("objectClass", "organization"); ModifyOperation modifyOperation = processModify("ou=People," + baseDN, add(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that increments a single-valued * integer attribute by one. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessIncrementByOne(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); LDAPAttribute attr = newLDAPAttribute("employeeNumber", "1"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); Entry e = DirectoryServer.getEntry(DN.valueOf("uid=test.user," + baseDN)); List attrList = e.getAttribute(DirectoryServer.getAttributeType("employeenumber", true)); assertNotNull(attrList); assertIntegerValueExists(attrList, 2); } /** * Tests the ability to perform a modification that increments a single-valued * integer attribute by ten. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessIncrementByTen(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); LDAPAttribute attr = newLDAPAttribute("employeeNumber", "10"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); Entry e = DirectoryServer.getEntry(DN.valueOf("uid=test.user," + baseDN)); List attrList = e.getAttribute(DirectoryServer.getAttributeType("employeenumber", true)); assertNotNull(attrList); assertIntegerValueExists(attrList, 11); } /** * Tests the ability to perform a modification that increments a single-valued * integer attribute by negative one. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessIncrementByNegativeOne(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); LDAPAttribute attr = newLDAPAttribute("employeeNumber", "-1"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); Entry e = DirectoryServer.getEntry(DN.valueOf("uid=test.user," + baseDN)); List attrList = e.getAttribute(DirectoryServer.getAttributeType("employeenumber", true)); assertNotNull(attrList); assertIntegerValueExists(attrList, 0); } private void assertIntegerValueExists(List attrList, int expectedValue) { boolean found = false; for (Attribute a : attrList) { for (AttributeValue v : a) { assertEquals(Integer.parseInt(v.getValue().toString()), expectedValue); found = true; } } assertTrue(found); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * increment a non-numeric attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailIncrementNonNumeric(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("displayName", "1"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * increment a non-numeric attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailIncrementValueNonNumeric(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: 1"); LDAPAttribute attr = newLDAPAttribute("description", "notnumeric"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that increments a multivalued * integer attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessIncrementMultiValued(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "roomNumber: 1", "roomNumber: 2"); LDAPAttribute attr = newLDAPAttribute("roomNumber", "1"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * perform an increment with no increment values in the request. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailIncrementNoIncrementValues(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "roomNumber: 1"); LDAPAttribute attr = new LDAPAttribute("roomNumber"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * perform an increment with multiple increment values in the request. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailIncrementMultipleIncrementValues(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "roomNumber: 1"); LDAPAttribute attr = newLDAPAttribute("roomNumber", "1", "2"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * increment a nonexisting attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailIncrementNonExisting(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("employeeNumber", "1"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests the ability to perform a modification that removes an unneeded * auxiliary objectclass. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessRemoveUnneededAuxiliaryObjectClass(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "objectClass: extensibleObject", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); LDAPAttribute attr = newLDAPAttribute("objectClass", "extensibleObject"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); Entry e = DirectoryServer.getEntry(DN.valueOf("uid=test.user," + baseDN)); assertFalse(e.hasObjectClass( DirectoryServer.getObjectClass("extensibleobject", true))); } /** * Tests the ability to perform a modification that adds an auxiliary * objectclass. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessAddAuxiliaryObjectClass(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); LDAPAttribute attr = newLDAPAttribute("objectClass", "extensibleObject"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); Entry e = DirectoryServer.getEntry(DN.valueOf("uid=test.user," + baseDN)); assertTrue(e.hasObjectClass(DirectoryServer.getObjectClass("extensibleobject", true))); assertTrue(e.hasObjectClass(DirectoryServer.getObjectClass("inetOrgPerson", true))); assertTrue(e.hasObjectClass(DirectoryServer.getObjectClass("organizationalPerson", true))); assertTrue(e.hasObjectClass(DirectoryServer.getObjectClass("person", true))); assertTrue(e.hasObjectClass(DirectoryServer.getObjectClass("top", true))); assertEquals(e.getUserAttributes().size(), 8, "Incorrect number of user attributes"); } /** * Tests that an attempt to add an objectclass that already exists will fail. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailAddDuplicateObjectClass(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); LDAPAttribute attr = newLDAPAttribute("objectClass", "inetOrgPerson"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests that an attempt to remove an objectclass that doesn't exist will * fail. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailRemoveNonExistingObjectClass(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); LDAPAttribute attr = newLDAPAttribute("objectClass", "organizationalUnit"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * alter an attribute marked NO-USER-MODIFICATION. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailReplaceNoUserModification(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); 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); LDAPAttribute attr = newLDAPAttribute("entryUUID", "12345678-1234-1234-1234-1234567890ab"); List mods = new ArrayList(); mods.add(replace(attr)); long modifyRequests = ldapStatistics.getModifyRequests(); long modifyResponses = ldapStatistics.getModifyResponses(); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp( ByteString.valueOf("uid=test.user," + baseDN), mods); message = new LDAPMessage(2, modifyRequest); w.writeMessage(message); message = r.readMessage(); ModifyResponseProtocolOp modifyResponse = message.getModifyResponseProtocolOp(); assertFalse(modifyResponse.getResultCode() == 0); assertEquals(ldapStatistics.getModifyRequests(), modifyRequests+1); waitForModifyResponsesStat(modifyResponses+1); } /** * Tests to ensure that a modify attempt fails if the server is completely * read-only. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailServerCompletelyReadOnly(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); DirectoryServer.setWritabilityMode(WritabilityMode.DISABLED); LDAPAttribute attr = newLDAPAttribute("objectClass", "extensibleObject"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED); } /** * Tests to ensure that an internal modify attempt succeeds when the server is * in an internal-only writability mode. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSucceedServerInternalOnlyWritability(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); DirectoryServer.setWritabilityMode(WritabilityMode.INTERNAL_ONLY); LDAPAttribute attr = newLDAPAttribute("objectClass", "extensibleObject"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED); } /** * Tests to ensure that an external modify attempt fails when the server is in * an internal-only writability mode. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailServerInternalOnlyWritability(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); DirectoryServer.setWritabilityMode(WritabilityMode.INTERNAL_ONLY); 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); LDAPAttribute attr = newLDAPAttribute("objectClass", "extensibleObject"); List mods = new ArrayList(); mods.add(add(attr)); long modifyRequests = ldapStatistics.getModifyRequests(); long modifyResponses = ldapStatistics.getModifyResponses(); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp( ByteString.valueOf("uid=test.user," + baseDN), mods); message = new LDAPMessage(2, modifyRequest); w.writeMessage(message); message = r.readMessage(); ModifyResponseProtocolOp modifyResponse = message.getModifyResponseProtocolOp(); assertFalse(modifyResponse.getResultCode() == 0); assertEquals(ldapStatistics.getModifyRequests(), modifyRequests+1); waitForModifyResponsesStat(modifyResponses+1); DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED); } /** * Tests to ensure that a modify attempt fails if the backend is completely * read-only. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailBackendCompletelyReadOnly(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); Backend b = DirectoryServer.getBackend(DN.valueOf(baseDN)); b.setWritabilityMode(WritabilityMode.DISABLED); LDAPAttribute attr = newLDAPAttribute("objectClass", "extensibleObject"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); b.setWritabilityMode(WritabilityMode.ENABLED); } /** * Tests to ensure that an internal modify attempt succeeds when the backend * is in an internal-only writability mode. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSucceedBackendInternalOnlyWritability(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); Backend b = DirectoryServer.getBackend(DN.valueOf(baseDN)); b.setWritabilityMode(WritabilityMode.INTERNAL_ONLY); LDAPAttribute attr = newLDAPAttribute("objectClass", "extensibleObject"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); b.setWritabilityMode(WritabilityMode.ENABLED); } /** * Tests to ensure that an external modify attempt fails when the backend is * in an internal-only writability mode. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailBackendInternalOnlyWritability(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); Backend b = DirectoryServer.getBackend(DN.valueOf(baseDN)); b.setWritabilityMode(WritabilityMode.INTERNAL_ONLY); 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); LDAPAttribute attr = newLDAPAttribute("objectClass", "extensibleObject"); List mods = new ArrayList(); mods.add(add(attr)); long modifyRequests = ldapStatistics.getModifyRequests(); long modifyResponses = ldapStatistics.getModifyResponses(); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp( ByteString.valueOf("uid=test.user," + baseDN), mods); message = new LDAPMessage(2, modifyRequest); w.writeMessage(message); message = r.readMessage(); ModifyResponseProtocolOp modifyResponse = message.getModifyResponseProtocolOp(); assertFalse(modifyResponse.getResultCode() == 0); assertEquals(ldapStatistics.getModifyRequests(), modifyRequests+1); waitForModifyResponsesStat(modifyResponses+1); b.setWritabilityMode(WritabilityMode.ENABLED); } /** * Tests to ensure that change listeners are properly notified for a * successful modify operation. * * @throws Exception If an unexpected problem occurs. */ @Test() public void testSuccessNotifyChangeListeners() throws Exception { TestChangeNotificationListener changeListener = new TestChangeNotificationListener(); DirectoryServer.registerChangeNotificationListener(changeListener); assertEquals(changeListener.getModifyCount(), 0); LDAPAttribute attr = newLDAPAttribute("description", "foo"); ModifyOperation modifyOperation = processModify("o=test", replace(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); assertEquals(changeListener.getModifyCount(), 1); DirectoryServer.deregisterChangeNotificationListener(changeListener); } /** * Tests to ensure that change listeners are not notified for a failed modify * modify operation. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailDoNotNotifyChangeListeners(String baseDN) throws Exception { TestChangeNotificationListener changeListener = new TestChangeNotificationListener(); DirectoryServer.registerChangeNotificationListener(changeListener); assertEquals(changeListener.getModifyCount(), 0); LDAPAttribute attr = newLDAPAttribute("dc", "foo"); ModifyOperation modifyOperation = processModify(baseDN, replace(attr)); assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); assertEquals(changeListener.getModifyCount(), 0); DirectoryServer.deregisterChangeNotificationListener(changeListener); } /** * Tests a modify operation that gets canceled before startup. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testCancelBeforeStartup(String baseDN) throws Exception { LDAPAttribute attr = newLDAPAttribute("description", "foo"); List mods = new ArrayList(); mods.add(replace(attr)); ModifyOperation modifyOperation = newModifyOperation(null, ByteString.valueOf(baseDN), mods); CancelRequest cancelRequest = new CancelRequest(false, LocalizableMessage.raw("testCancelBeforeStartup")); modifyOperation.abort(cancelRequest); modifyOperation.run(); assertEquals(modifyOperation.getResultCode(), ResultCode.CANCELED); } /** * Tests a modify operation that gets canceled before startup. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testCancelAfterOperation(String baseDN) throws Exception { LDAPAttribute attr = newLDAPAttribute("description", "foo"); List mods = new ArrayList(); mods.add(replace(attr)); ModifyOperation modifyOperation = newModifyOperation(null, ByteString.valueOf(baseDN), mods); modifyOperation.run(); CancelRequest cancelRequest = new CancelRequest(false, LocalizableMessage.raw("testCancelBeforeStartup")); CancelResult cancelResponse = modifyOperation.cancel(cancelRequest); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); assertEquals(cancelResponse.getResultCode(), ResultCode.TOO_LATE); } /** * Tests a modify 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(dataProvider = "baseDNs", groups = { "slow" }) public void testCannotLockEntry(String baseDN) throws Exception { Lock entryLock = LockManager.lockRead(DN.valueOf(baseDN)); try { LDAPAttribute attr = newLDAPAttribute("description", "foo"); ModifyOperation modifyOperation = processModify(baseDN, replace(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.BUSY); } finally { LockManager.unlock(DN.valueOf(baseDN), entryLock); } } /** * Tests a modify operation that should be disconnected in a pre-parse plugin. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testDisconnectInPreParseModify(String baseDN) throws Exception { 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); LDAPAttribute attr = newLDAPAttribute("description", "foo"); List mods = new ArrayList(); mods.add(replace(attr)); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp(ByteString.valueOf(baseDN), mods); message = new LDAPMessage(2, modifyRequest, 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); } StaticUtils.close(s); } /** * Tests a modify operation that should be disconnected in a pre-operation * plugin. * * @throws Exception If an unexpected problem occurs. */ @Test() public void testDisconnectInPreOperationModify() throws Exception { 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); LDAPAttribute attr = newLDAPAttribute("description", "foo"); List mods = new ArrayList(); mods.add(replace(attr)); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp(ByteString.valueOf("o=test"), mods); message = new LDAPMessage(2, modifyRequest, 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); } StaticUtils.close(s); } /** * Tests a modify operation that should be disconnected in a post-operation * plugin. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testDisconnectInPostOperationModify(String baseDN) throws Exception { 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); LDAPAttribute attr = newLDAPAttribute("description", "foo"); List mods = new ArrayList(); mods.add(replace(attr)); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp(ByteString.valueOf(baseDN), mods); message = new LDAPMessage(2, modifyRequest, DisconnectClientPlugin.createDisconnectControlList( "PostOperation")); w.writeMessage(message); // The operation should NOT be aborted at the post operation stage. While // the plugin can disconnect the client, the modify should have already // been committed to the backend and a SUCCESS COULD get back to the // client. responseLoop: while (true) { message = r.readMessage(); if (message == null) { // The connection has been closed. break responseLoop; } switch (message.getProtocolOpType()) { case OP_TYPE_MODIFY_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. StaticUtils.close(s); throw new Exception("Unexpected response message " + message + " encountered in " + "testDisconnectInPostOperationModify"); } } StaticUtils.close(s); } /** * Tests a modify operation that should be disconnected in a post-response * plugin. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testDisconnectInPostResponseModify(String baseDN) throws Exception { 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); LDAPAttribute attr = newLDAPAttribute("description", "foo"); List mods = new ArrayList(); mods.add(replace(attr)); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp(ByteString.valueOf(baseDN), mods); message = new LDAPMessage(2, modifyRequest, 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_MODIFY_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. StaticUtils.close(s); throw new Exception("Unexpected response message " + message + " encountered in " + "testDisconnectInPostResponseModify"); } } StaticUtils.close(s); } /** * Tests a modify operation that attemtps to set a value for an attribute type * that is marked OBSOLETE in the server schema. * * @param baseDN The base DN for the test backend. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testModifyObsoleteAttribute(String baseDN) throws Exception { String path = TestCaseUtils.createTempFile( "dn: cn=schema", "changetype: modify", "add: attributeTypes", "attributeTypes: ( testmodifyobsoleteattribute-oid " + "NAME 'testModifyObsoleteAttribute' OBSOLETE " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE " + "X-ORGIN 'SchemaBackendTestCase' )"); String attrName = "testmodifyobsoleteattribute"; 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: " + baseDN, "changetype: modify", "add: objectClass", "objectClass: extensibleObject", "-", "replace: testModifyObsoleteAttribute", "testModifyObsoleteAttribute: 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 a modify operation that attemtps to add an OBSOLETE object class to * an entry. * * @param baseDN The base DN for the test backend. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testModifyAddObsoleteObjectClass(String baseDN) throws Exception { String path = TestCaseUtils.createTempFile( "dn: cn=schema", "changetype: modify", "add: objectClasses", "objectClasses: ( testmodifyaddobsoleteobjectclass-oid " + "NAME 'testModifyAddObsoleteObjectClass' OBSOLETE " + "AUXILIARY MAY description X-ORGIN 'SchemaBackendTestCase' )"); String ocName = "testmodifyaddobsoleteobjectclass"; 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: " + baseDN, "changetype: modify", "add: objectClass", "objectClass: testModifyAddObsoleteObjectClass"); 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 a modify * operation in the pre-parse phase with a success result code. * * @throws Exception If an unexpected problem occurs. */ @Test() public void testShortCircuitInPreParse() throws Exception { List controls = ShortCircuitPlugin.createShortCircuitControlList(0, "PreParse"); List mods = new ArrayList(); mods.add(RawModification.create(ModificationType.REPLACE, "description", "foo")); ModifyOperation modifyOperation = newModifyOperation(controls, ByteString.valueOf("o=test"), mods); modifyOperation.run(); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); assertTrue(DirectoryServer.entryExists(DN.valueOf("o=test"))); assertFalse(DirectoryServer.getEntry(DN.valueOf("o=test")).hasAttribute( DirectoryServer.getAttributeType("description", true))); } /** * Tests modify operation with the Permissive Modify control. */ /** * Test to ensure that a modify operation with the Permissive Modify control * succeeds when an attempt is made to add a value that matches one * that already exists. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessPermissiveModifyControlAddDuplicateValue(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("givenName", "Test"); List mods = new ArrayList(); mods.add(add(attr)); List requestControls = new ArrayList(); requestControls.add( new LDAPControl(ServerConstants.OID_PERMISSIVE_MODIFY_CONTROL, false)); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, mods, requestControls); assertTrue(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Test to ensure that a modify operation with the Permissive Modify control * succeeds when an attempt is made to delete a non existent value. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessPermissiveModifyControlRemoveNonExistentValue(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = newLDAPAttribute("givenName", "Foo"); List mods = new ArrayList(); mods.add(delete(attr)); List requestControls = new ArrayList(); requestControls.add( new LDAPControl(ServerConstants.OID_PERMISSIVE_MODIFY_CONTROL, false)); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, mods, requestControls); assertTrue(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Test to ensure that a modify operation with the Permissive Modify control * succeeds when an attempt is made to delete a non existent attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testSuccessPermissiveModifyControlRemoveNonExistentAttribute(String baseDN) throws Exception { processAdd( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); LDAPAttribute attr = new LDAPAttribute("description"); List mods = new ArrayList(); mods.add(delete(attr)); List requestControls = new ArrayList(); requestControls.add( new LDAPControl(ServerConstants.OID_PERMISSIVE_MODIFY_CONTROL, false)); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, mods, requestControls); assertTrue(modifyOperation.getResultCode() == ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); } /** * Tests a modify operation that attempts change the user password doing * a delete of all values followed of an add of a new value. * * @param baseDN The base DN for the test backend. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testModifyDelAddPasswordAttribute(String baseDN) throws Exception { processAdd( "dn: uid=testPassword01.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); String path = TestCaseUtils.createTempFile( "dn: uid=testPassword01.user," + baseDN, "changetype: modify", "delete: userPassword", "-", "add: userPassword", "userPassword: aNewPassword"); 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); } /** * Tests a modify operation that attempts change the user password doing * a delete of a clear text value followed of an add of a new value. * * @param baseDN The base DN for the test backend. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testModifyDelOneAddOnePasswordAttribute(String baseDN) throws Exception { processAdd( "dn: uid=testPassword02.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); String path = TestCaseUtils.createTempFile( "dn: uid=testPassword02.user," + baseDN, "changetype: modify", "delete: userPassword", "userPassword: password", "-", "add: userPassword", "userPassword: aNewPassword"); 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); } /** * Tests a modify operation that attempts change the user password doing * a delete of an encrypted value followed of an add of a new value. * * @param baseDN The base DN for the test backend. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testModifyDelEncryptedAddOnePasswordAttribute(String baseDN) throws Exception { processAdd( "dn: uid=testPassword03.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); Entry e = DirectoryServer.getEntry( DN.valueOf("uid=testPassword03.user," + baseDN)); List attrList = e.getAttribute(DirectoryServer.getAttributeType("userpassword", true)); assertNotNull(attrList); String passwd = null; for (Attribute a : attrList) { for (AttributeValue v : a) { passwd = v.toString(); } } assertNotNull(passwd); String path = TestCaseUtils.createTempFile( "dn: uid=testPassword03.user," + baseDN, "changetype: modify", "delete: userPassword", "userPassword: " + passwd, "-", "add: userPassword", "userPassword: aNewPassword"); 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); } /** * Tests that it is possible to delete userPassword attributes which have * options. Options are not allowed for passwords, but we should allow users * to clean them up, for example, after an import of legacy data. * * @throws Exception * If an unexpected problem occurs. */ @Test public void testModifyDelPasswordAttributeWithOption() throws Exception { // @formatter:off Entry e = TestCaseUtils.makeEntry( "dn: cn=Test User,o=test", "objectClass: top", "objectClass: person", "sn: User", "cn: Test User", "userPassword: password", "userPassword;deleted: oldpassword"); Backend backend = DirectoryServer.getBackend(TEST_BACKEND_ID); backend.addEntry(e, null); // Don't use add operation. // Constraint violation. assertEquals(TestCaseUtils.applyModifications(false, "dn: cn=Test User,o=test", "changetype: modify", "delete: userPassword;deleted", "-" ), 0); // @formatter:on e = DirectoryServer.getEntry(DN.valueOf("cn=Test User,o=test")); List attrList = e.getAttribute("userpassword"); assertNotNull(attrList); assertEquals(attrList.size(), 1); assertFalse(attrList.get(0).hasOptions()); assertEquals(attrList.get(0).size(), 1); } /** * Tests that it is possible to delete userPassword attributes using an empty * replace which have options. Options are not allowed for passwords, but we * should allow users to clean them up, for example, after an import of legacy * data. * * @throws Exception * If an unexpected problem occurs. */ @Test public void testModifyReplaceEmptyPasswordAttributeWithOption() throws Exception { // @formatter:off Entry e = TestCaseUtils.makeEntry( "dn: cn=Test User,o=test", "objectClass: top", "objectClass: person", "sn: User", "cn: Test User", "userPassword: password", "userPassword;deleted: oldpassword"); Backend backend = DirectoryServer.getBackend(TEST_BACKEND_ID); backend.addEntry(e, null); // Don't use add operation. // Constraint violation. assertEquals(TestCaseUtils.applyModifications(false, "dn: cn=Test User,o=test", "changetype: modify", "replace: userPassword;deleted", "-" ), 0); // @formatter:on e = DirectoryServer.getEntry(DN.valueOf("cn=Test User,o=test")); List attrList = e.getAttribute("userpassword"); assertNotNull(attrList); assertEquals(attrList.size(), 1); assertFalse(attrList.get(0).hasOptions()); assertEquals(attrList.get(0).size(), 1); } /** * Tests that it is not possible to add userPassword attributes which have * options. Options are not allowed for passwords. * * @throws Exception * If an unexpected problem occurs. */ @Test public void testModifyAddPasswordAttributeWithOption() throws Exception { // @formatter:off TestCaseUtils.addEntry( "dn: cn=Test User,o=test", "objectClass: top", "objectClass: person", "sn: User", "cn: Test User", "userPassword: password"); // Constraint violation. assertEquals(TestCaseUtils.applyModifications(false, "dn: cn=Test User,o=test", "changetype: modify", "add: userPassword;added", "userPassword;added: newpassword", "-" ), 19); // @formatter:on Entry e = DirectoryServer.getEntry(DN.valueOf("cn=Test User,o=test")); List attrList = e.getAttribute("userpassword"); assertNotNull(attrList); assertEquals(attrList.size(), 1); assertFalse(attrList.get(0).hasOptions()); assertEquals(attrList.get(0).size(), 1); } /** * Tests that it is not possible to add userPassword attributes which have * options. Options are not allowed for passwords. * * @throws Exception * If an unexpected problem occurs. */ @Test public void testModifyReplaceWithValuesPasswordAttributeWithOption() throws Exception { // @formatter:off TestCaseUtils.addEntry( "dn: cn=Test User,o=test", "objectClass: top", "objectClass: person", "sn: User", "cn: Test User", "userPassword: password"); // Constraint violation. assertEquals(TestCaseUtils.applyModifications(false, "dn: cn=Test User,o=test", "changetype: modify", "replace: userPassword;added", "userPassword;added: newpassword", "-" ), 19); // @formatter:on Entry e = DirectoryServer.getEntry(DN.valueOf("cn=Test User,o=test")); List attrList = e.getAttribute("userpassword"); assertNotNull(attrList); assertEquals(attrList.size(), 1); assertFalse(attrList.get(0).hasOptions()); assertEquals(attrList.get(0).size(), 1); } /** * Tests that the binary option is automatically added to modifications if it * is missing and required. * * @throws Exception * If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testAddCertificateWithoutBinaryOption(String baseDN) throws Exception { TestCaseUtils.addEntry( "dn: uid=test.user," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password", "mail: foo", "employeeNumber: 1"); String certificateValue = "MIICpTCCAg6gAwIBAgIJALeoA6I3ZC/cMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV" + "BAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRpb25lMRwwGgYDVQQLExNQcm9kdWN0IERl" + "dmVsb3BtZW50MRQwEgYDVQQDEwtCYWJzIEplbnNlbjAeFw0xMjA1MDIxNjM0MzVa" + "Fw0xMjEyMjExNjM0MzVaMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRp" + "b25lMRwwGgYDVQQLExNQcm9kdWN0IERldmVsb3BtZW50MRQwEgYDVQQDEwtCYWJz" + "IEplbnNlbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApysa0c9qc8FB8gIJ" + "8zAb1pbJ4HzC7iRlVGhRJjFORkGhyvU4P5o2wL0iz/uko6rL9/pFhIlIMbwbV8sm" + "mKeNUPitwiKOjoFDmtimcZ4bx5UTAYLbbHMpEdwSpMC5iF2UioM7qdiwpAfZBd6Z" + "69vqNxuUJ6tP+hxtr/aSgMH2i8ECAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB" + "hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE" + "FLlZD3aKDa8jdhzoByOFMAJDs2osMB8GA1UdIwQYMBaAFLlZD3aKDa8jdhzoByOF" + "MAJDs2osMA0GCSqGSIb3DQEBBQUAA4GBAE5vccY8Ydd7by2bbwiDKgQqVyoKrkUg" + "6CD0WRmc2pBeYX2z94/PWO5L3Fx+eIZh2wTxScF+FdRWJzLbUaBuClrxuy0Y5ifj" + "axuJ8LFNbZtsp1ldW3i84+F5+SYT+xI67ZcoAtwx/VFVI9s5I/Gkmu9f9nxjPpK7" + "1AIUXiE3Qcck"; ArrayList values = new ArrayList(); values.add(ByteString.wrap(Base64.decode(certificateValue))); LDAPAttribute attr = new LDAPAttribute("usercertificate", values); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); Entry e = DirectoryServer.getEntry(DN.valueOf("uid=test.user," + baseDN)); List attrList = e.getAttribute(DirectoryServer.getAttributeType("usercertificate", true)); assertNotNull(attrList); assertEquals(attrList.size(), 1); Attribute a = attrList.get(0); assertTrue(a.hasOption("binary")); assertEquals(a.size(), 1); assertEquals(Base64.encode(a.iterator().next().getValue()), certificateValue); } /** * Tests to ensure that the compressed schema is refreshed after an object * class is changed (OPENDJ-169). * * @throws Exception * If an unexpected problem occurs. */ @Test public void testCompressedSchemaRefresh() throws Exception { String baseDN = "dc=example,dc=com"; TestCaseUtils.clearJEBackend(true, "userRoot", baseDN); processAdd("dn: cn=Test User," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "sn: User", "cn: Test User"); // First check that adding "dc" fails because it is not allowed by // inetOrgPerson. LDAPAttribute attr = newLDAPAttribute("dc", "foo"); List mods = new ArrayList(); mods.add(add(attr)); ModifyOperation modifyOperation = processModify("cn=Test User," + baseDN, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.OBJECTCLASS_VIOLATION); int res = applyModifications( false, "dn: cn=schema", "changetype: modify", "delete: objectclasses", "objectClasses: ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn )" + " MAY ( userPassword $ telephoneNumber $ seeAlso $ description )" + " X-ORIGIN 'RFC 4519' )", "-", "add: objectclasses", "objectClasses: ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn )" + " MAY ( dc $ userPassword $ telephoneNumber $ seeAlso $ description )" + " X-ORIGIN 'RFC 4519' )"); assertEquals(res, 0, "Schema update failed"); try { // Modify existing entry. modifyOperation = processModify("cn=Test User," + baseDN, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); // Add new entry and modify. processAdd("dn: cn=Test User2," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "sn: User2", "cn: Test User2"); modifyOperation = processModify("cn=Test User2," + baseDN, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); } finally { int result = applyModifications( false, "dn: cn=schema", "changetype: modify", "delete: objectclasses", "objectClasses: ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn )" + " MAY ( dc $ userPassword $ telephoneNumber $ seeAlso $ description )" + " X-ORIGIN 'RFC 4519' )", "-", "add: objectclasses", "objectClasses: ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn )" + " MAY ( userPassword $ telephoneNumber $ seeAlso $ description )" + " X-ORIGIN 'RFC 4519' )"); assertEquals(result, 0, "Schema update failed"); // Add new entry and modify (this time it should fail). processAdd("dn: cn=Test User3," + baseDN, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "sn: User3", "cn: Test User3"); modifyOperation = processModify("cn=Test User3," + baseDN, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.OBJECTCLASS_VIOLATION); } } }