/* * 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-2015 ForgeRock AS */ package org.opends.server.core; import java.net.Socket; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.opendj.ldap.ByteString; import org.forgerock.opendj.ldap.ModificationType; import org.forgerock.opendj.ldap.ResultCode; 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.internal.SearchRequest; import org.opends.server.protocols.ldap.BindRequestProtocolOp; import org.opends.server.protocols.ldap.BindResponseProtocolOp; import org.opends.server.protocols.ldap.LDAPAttribute; import org.opends.server.protocols.ldap.LDAPControl; import org.opends.server.protocols.ldap.LDAPMessage; import org.opends.server.protocols.ldap.LDAPModification; import org.opends.server.protocols.ldap.ModifyRequestProtocolOp; import org.opends.server.protocols.ldap.ModifyResponseProtocolOp; import org.opends.server.tools.LDAPModify; import org.opends.server.tools.LDAPWriter; import org.opends.server.types.Attribute; import org.opends.server.types.Attributes; import org.opends.server.types.CancelRequest; import org.opends.server.types.CancelResult; import org.opends.server.types.Control; import org.opends.server.types.DN; import org.opends.server.types.DirectoryException; import org.opends.server.types.Entry; import org.opends.server.types.LockManager.DNLock; import org.opends.server.types.Modification; import org.opends.server.types.Operation; import org.opends.server.types.RawModification; import org.opends.server.types.WritabilityMode; 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.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import static org.opends.server.TestCaseUtils.*; import static org.opends.server.protocols.internal.InternalClientConnection.*; import static org.opends.server.protocols.internal.Requests.*; import static org.opends.server.protocols.ldap.LDAPConstants.*; import static org.opends.server.util.CollectionUtils.*; 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 { for (Object[] backendBaseDN2 : getBaseDNs()) { final DN baseDN = DN.valueOf(backendBaseDN2[0].toString()); Backend<?> b = DirectoryServer.getBackend(baseDN); 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<ModifyOperation> opList = new ArrayList<>(); List<Control> noControls = new ArrayList<>(); LDAPAttribute ldapAttr = new LDAPAttribute("description", "foo"); List<RawModification> ldapMods = newRawModifications(add(ldapAttr)); opList.add(newModifyOperation(null, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(null, ByteString.valueOfUtf8("o=test"), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.valueOfUtf8("o=test"), ldapMods)); ldapMods = newRawModifications(delete(ldapAttr)); opList.add(newModifyOperation(null, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(null, ByteString.valueOfUtf8("o=test"), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.valueOfUtf8("o=test"), ldapMods)); ldapMods = newRawModifications(replace(ldapAttr)); opList.add(newModifyOperation(null, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(null, ByteString.valueOfUtf8("o=test"), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.valueOfUtf8("o=test"), ldapMods)); String value2 = "bar"; LDAPAttribute ldapAttr2 = new LDAPAttribute("description", value2); ldapMods = newRawModifications(delete(ldapAttr), add(ldapAttr2)); opList.add(newModifyOperation(null, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(null, ByteString.valueOfUtf8("o=test"), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.valueOfUtf8("o=test"), ldapMods)); ldapAttr2 = new LDAPAttribute("cn", value2); ldapMods = newRawModifications(replace(ldapAttr), replace(ldapAttr2)); opList.add(newModifyOperation(null, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.empty(), ldapMods)); opList.add(newModifyOperation(null, ByteString.valueOfUtf8("o=test"), ldapMods)); opList.add(newModifyOperation(noControls, ByteString.valueOfUtf8("o=test"), ldapMods)); List<Modification> mods = newModifications(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 = newModifications(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 = newModifications(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 = newModifications( new Modification(ModificationType.DELETE, Attributes.create("description", "foo")), 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 = newModifications( new Modification(ModificationType.REPLACE, Attributes.create("description", "foo")), 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<Control> requestControls, DN entryDn, List<Modification> modifications) { return new ModifyOperationBasis( getRootConnection(), nextOperationID(), nextMessageID(), requestControls, entryDn, modifications); } private ModifyOperation newModifyOperation(List<Control> requestControls, ByteString rawEntryDn, List<RawModification> rawModifications) { return new ModifyOperationBasis( getRootConnection(), nextOperationID(), 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 <CODE>getRawEntryDN</CODE> and <CODE>setRawEntryDN</CODE> * 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.valueOfUtf8("uid=test,o=test")); assertNotNull(modifyOperation.getRawEntryDN()); assertEquals(modifyOperation.getRawEntryDN(), ByteString.valueOfUtf8("uid=test,o=test")); modifyOperation.setRawEntryDN(originalDN); assertNotNull(modifyOperation.getRawEntryDN()); assertEquals(modifyOperation.getRawEntryDN(), originalDN); } /** * Tests the <CODE>getEntryDN</CODE> method that should decode * the raw entry dn and return a non-null DN. */ @Test public void testGetEntryDNInitiallyNull() { LDAPAttribute attr = newLDAPAttribute("description", "foo"); List<RawModification> mods = newRawModifications(replace(attr)); ModifyOperation modifyOperation = newModifyOperation(null, ByteString.empty(), mods); assertNotNull(modifyOperation.getEntryDN()); } private LDAPAttribute newLDAPAttribute(String attributeType, String... valueStrings) { return new LDAPAttribute(attributeType, newArrayList(valueStrings)); } /** * Tests the <CODE>getEntryDN</CODE> method for the case in which we expect * the DN to be initially non-null. * * @throws Exception If an unexpected problem occurs. */ @Test public void testGetEntryDNInitiallyNonNull() throws Exception { List<Modification> mods = newModifications( new Modification(ModificationType.REPLACE, Attributes.create("description", "foo"))); ModifyOperation modifyOperation = newModifyOperation(null, DN.rootDN(), mods); assertNotNull(modifyOperation.getEntryDN()); } /** * Tests the <CODE>getEntryDN</CODE> 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 <CODE>getEntryDN</CODE>. * * @throws Exception If an unexpected problem occurs. */ @Test public void testGetEntryDNNonNullChangedToNull() throws Exception { List<Modification> mods = newModifications( new Modification(ModificationType.REPLACE, Attributes.create("description", "foo"))); ModifyOperation modifyOperation = newModifyOperation(null, DN.rootDN(), mods); assertNotNull(modifyOperation.getEntryDN()); modifyOperation.setRawEntryDN(ByteString.valueOfUtf8("ou=Users,o=test")); assertNotNull(modifyOperation.getEntryDN()); } /** * Tests the <CODE>getRawModifications</CODE>, * <CODE>addRawModification</CODE>, and <CODE>setRawModifications</CODE> * methods. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "modifyOperations") public void testGetAndSetRawModifications(ModifyOperation modifyOperation) throws Exception { List<RawModification> rawMods = modifyOperation.getRawModifications(); List<RawModification> 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); @SuppressWarnings("unchecked") List<LocalBackendModifyOperation> localOps = (List<LocalBackendModifyOperation>) modifyOperation.getAttachment(Operation.LOCALBACKENDOPERATIONS); assertNotNull(localOps); for (LocalBackendModifyOperation curOp : localOps) { curOp.getNewPasswords(); curOp.getCurrentPasswords(); assertNotNull(curOp.getCurrentEntry()); assertNotNull(curOp.getModifiedEntry()); } } /** * 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); } /** * Tests the <CODE>getModifications</CODE> and <CODE>addModification</CODE> * 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.getAttributeTypeOrDefault("description"))); UpdatePreOpPlugin.reset(); UpdatePreOpPlugin.addModification( new Modification(ModificationType.REPLACE, Attributes.create("description", "foo"))); List<Modification> mods = newModifications( new Modification(ModificationType.REPLACE, Attributes.create("l", "Austin"))); ModifyOperation modifyOperation = getRootConnection().processModify(DN.valueOf("o=test"), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); e = DirectoryServer.getEntry(DN.valueOf("o=test")); assertNotNull(e.getAttribute(DirectoryServer.getAttributeTypeOrDefault("description"))); 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)); assertNotEquals(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)); assertNotEquals(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)); assertNotEquals(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)); assertNotEquals(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); assertNotEquals(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.getAttributeTypeOrDefault("description"))); 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.getAttributeTypeOrDefault("description"))); } /** * 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<Attribute> attrList = e.getAttribute(DirectoryServer.getAttributeTypeOrDefault("o")); 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.getAttributeTypeOrDefault("o")); 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<Attribute> attrList = e.getAttribute(DirectoryServer.getAttributeTypeOrDefault("o")); 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.getAttributeTypeOrDefault("o")); assertEquals(countValues(attrList), 2); } private int countValues(List<Attribute> 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 { 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"); LDAPAttribute attr = newLDAPAttribute("displayName", "foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertNotEquals(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 { 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", "ds-pwp-account-disabled: true"); LDAPAttribute attr = newLDAPAttribute("ds-pwp-account-disabled", "false"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertNotEquals(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 { 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"); LDAPAttribute attr = newLDAPAttribute("displayName", "foo", "bar"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertNotEquals(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 { 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"); LDAPAttribute attr = newLDAPAttribute("ds-pwp-account-disabled", "true", "false"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertNotEquals(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<RawModification> mods) { InternalClientConnection conn = getRootConnection(); return conn.processModify(ByteString.valueOfUtf8(entryDN), mods); } private ModifyOperation processModify(String entryDN, RawModification... mods) { InternalClientConnection conn = getRootConnection(); return conn.processModify(ByteString.valueOfUtf8(entryDN), Arrays.asList(mods)); } private ModifyOperation processModify(String entryDN, List<RawModification> mods, List<Control> requestControls) { InternalClientConnection conn = getRootConnection(); return conn.processModify(ByteString.valueOfUtf8(entryDN), mods, requestControls); } /** * 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 { 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"); LDAPAttribute attr = newLDAPAttribute("givenName", "Test"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertNotEquals(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 { 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"); LDAPAttribute attr = newLDAPAttribute("description", "Foo", "Foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertNotEquals(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 { 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", "manager: cn=boss," + baseDN); LDAPAttribute attr = newLDAPAttribute("manager", "invaliddn"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertNotEquals(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 { 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"); LDAPAttribute attr = newLDAPAttribute("manager", "invaliddn"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertNotEquals(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 { 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"); 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 { 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"); 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 { 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"); LDAPAttribute attr = newLDAPAttribute("uid", "foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertNotEquals(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 { 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"); LDAPAttribute attr = new LDAPAttribute("uid"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertNotEquals(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 { 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"); LDAPAttribute attr = newLDAPAttribute("uid", "test.user"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertNotEquals(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 { TestCaseUtils.addEntry( "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)); assertNotEquals(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 { TestCaseUtils.addEntry( "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)); assertNotEquals(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 { 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"); 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 { 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", "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 { 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"); 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 { 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", "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 { 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"); LDAPAttribute attr = new LDAPAttribute("sn"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertNotEquals(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 { 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"); LDAPAttribute attr = newLDAPAttribute("sn", "User"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertNotEquals(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 { 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"); 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 { 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"); String dn = "uid=test.user," + baseDN; LDAPAttribute attr = newLDAPAttribute("uid", "test.user"); ModifyOperation modifyOperation = processModify(dn, replace(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); SearchRequest request = newSearchRequest(dn, SearchScope.WHOLE_SUBTREE, "(uid=test.user)"); InternalSearchOperation searchOperation = getRootConnection().processSearch(request); 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 { 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"); LDAPAttribute attr = newLDAPAttribute("cn", "Test User"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr), add(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveSuccessfulOperationElements(modifyOperation); SearchRequest request = newSearchRequest(baseDN, SearchScope.WHOLE_SUBTREE, "(cn=Test User)"); InternalSearchOperation searchOperation = getRootConnection().processSearch(request); 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 { 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", "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); SearchRequest request = newSearchRequest(baseDN, SearchScope.WHOLE_SUBTREE, "(givenName;lang-de=X)"); InternalSearchOperation searchOperation = getRootConnection().processSearch(request); 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 { 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"); 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 { 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"); 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 { 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"); 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 { 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"); 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 { 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", "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 { 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"); 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 { 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", "userPassword: password"); LDAPAttribute attr = new LDAPAttribute("displayName"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertNotEquals(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 { 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"); LDAPAttribute attr = newLDAPAttribute("displayName", "Foo"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertNotEquals(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 { 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"); LDAPAttribute attr = new LDAPAttribute("objectClass"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertNotEquals(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 { 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"); LDAPAttribute attr = new LDAPAttribute("objectClass"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, replace(attr)); assertNotEquals(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 { TestCaseUtils.addEntry( "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)); assertNotEquals(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 { TestCaseUtils.addEntry( "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)); assertNotEquals(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 { 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"); 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<Attribute> attrList = e.getAttribute(DirectoryServer.getAttributeTypeOrDefault("employeenumber")); 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 { 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"); 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<Attribute> attrList = e.getAttribute(DirectoryServer.getAttributeTypeOrDefault("employeenumber")); 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 { 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"); 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<Attribute> attrList = e.getAttribute(DirectoryServer.getAttributeTypeOrDefault("employeenumber")); assertNotNull(attrList); assertIntegerValueExists(attrList, 0); } private void assertIntegerValueExists(List<Attribute> attrList, int expectedValue) { boolean found = false; for (Attribute a : attrList) { for (ByteString v : a) { assertEquals(Integer.parseInt(v.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 { 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"); LDAPAttribute attr = newLDAPAttribute("displayName", "1"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertNotEquals(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 { 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: 1"); LDAPAttribute attr = newLDAPAttribute("description", "notnumeric"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertNotEquals(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 { 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", "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 { 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", "roomNumber: 1"); LDAPAttribute attr = new LDAPAttribute("roomNumber"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertNotEquals(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 { 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", "roomNumber: 1"); LDAPAttribute attr = newLDAPAttribute("roomNumber", "1", "2"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertNotEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests to ensure that a modify attempt fails if an attempt is made to * increment a non existing attribute. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailIncrementNonExisting(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"); LDAPAttribute attr = newLDAPAttribute("employeeNumber", "1"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, increment(attr)); assertNotEquals(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 { TestCaseUtils.addEntry( "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 { 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"); 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 { 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"); LDAPAttribute attr = newLDAPAttribute("objectClass", "inetOrgPerson"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertNotEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); } /** * Tests that an attempt to remove an objectclass that does not exist will fail. * * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "baseDNs") public void testFailRemoveNonExistingObjectClass(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"); LDAPAttribute attr = newLDAPAttribute("objectClass", "organizationalUnit"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, delete(attr)); assertNotEquals(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 { 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"); 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.valueOfUtf8("cn=Directory Manager"), 3, ByteString.valueOfUtf8("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<RawModification> mods = newRawModifications(replace(attr)); long modifyRequests = ldapStatistics.getModifyRequests(); long modifyResponses = ldapStatistics.getModifyResponses(); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp( ByteString.valueOfUtf8("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 { 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"); DirectoryServer.setWritabilityMode(WritabilityMode.DISABLED); LDAPAttribute attr = newLDAPAttribute("objectClass", "extensibleObject"); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, add(attr)); assertNotEquals(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 { 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"); 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 { 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"); 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.valueOfUtf8("cn=Directory Manager"), 3, ByteString.valueOfUtf8("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<RawModification> mods = newRawModifications(add(attr)); long modifyRequests = ldapStatistics.getModifyRequests(); long modifyResponses = ldapStatistics.getModifyResponses(); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp( ByteString.valueOfUtf8("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 { 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"); 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)); assertNotEquals(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 { 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"); 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 { 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"); 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.valueOfUtf8("cn=Directory Manager"), 3, ByteString.valueOfUtf8("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<RawModification> mods = newRawModifications(add(attr)); long modifyRequests = ldapStatistics.getModifyRequests(); long modifyResponses = ldapStatistics.getModifyResponses(); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp( ByteString.valueOfUtf8("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.registerInternalPlugin(changeListener); try { 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); } finally { DirectoryServer.deregisterInternalPlugin(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.registerInternalPlugin(changeListener); try { assertEquals(changeListener.getModifyCount(), 0); LDAPAttribute attr = newLDAPAttribute("dc", "foo"); ModifyOperation modifyOperation = processModify(baseDN, replace(attr)); assertNotEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); retrieveFailedOperationElements(modifyOperation); assertEquals(changeListener.getModifyCount(), 0); } finally { DirectoryServer.deregisterInternalPlugin(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<RawModification> mods = newRawModifications(replace(attr)); ModifyOperation modifyOperation = newModifyOperation(null, ByteString.valueOfUtf8(baseDN), mods); CancelRequest cancelRequest = new CancelRequest(false, LocalizableMessage.raw("testCancelBeforeStartup")); modifyOperation.abort(cancelRequest); modifyOperation.run(); assertEquals(modifyOperation.getResultCode(), ResultCode.CANCELLED); } /** * 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<RawModification> mods = newRawModifications(replace(attr)); ModifyOperation modifyOperation = newModifyOperation(null, ByteString.valueOfUtf8(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 { final DNLock entryLock = DirectoryServer.getLockManager().tryReadLockEntry(DN.valueOf(baseDN)); try { LDAPAttribute attr = newLDAPAttribute("description", "foo"); ModifyOperation modifyOperation = processModify(baseDN, replace(attr)); assertEquals(modifyOperation.getResultCode(), ResultCode.BUSY); } finally { entryLock.unlock(); } } /** * 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.valueOfUtf8("cn=Directory Manager"), 3, ByteString.valueOfUtf8("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<RawModification> mods = newRawModifications(replace(attr)); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp(ByteString.valueOfUtf8(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.valueOfUtf8("cn=Directory Manager"), 3, ByteString.valueOfUtf8("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<RawModification> mods = newRawModifications(replace(attr)); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp(ByteString.valueOfUtf8("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.valueOfUtf8("cn=Directory Manager"), 3, ByteString.valueOfUtf8("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<RawModification> mods = newRawModifications(replace(attr)); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp(ByteString.valueOfUtf8(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.valueOfUtf8("cn=Directory Manager"), 3, ByteString.valueOfUtf8("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<RawModification> mods = newRawModifications(replace(attr)); ModifyRequestProtocolOp modifyRequest = new ModifyRequestProtocolOp(ByteString.valueOfUtf8(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); } private List<Modification> newModifications(Modification... mods) { return newArrayList(mods); } private List<RawModification> newRawModifications(RawModification... mods) { return newArrayList(mods); } /** * Tests a modify operation that attempts 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<Control> controls = ShortCircuitPlugin.createShortCircuitControlList(0, "PreParse"); List<RawModification> mods = newRawModifications( RawModification.create(ModificationType.REPLACE, "description", "foo")); ModifyOperation modifyOperation = newModifyOperation(controls, ByteString.valueOfUtf8("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.getAttributeTypeOrDefault("description"))); } /** * 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 { 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"); LDAPAttribute attr = newLDAPAttribute("givenName", "Test"); List<RawModification> mods = newRawModifications(add(attr)); List<Control> requestControls = new ArrayList<>(); requestControls.add( new LDAPControl(ServerConstants.OID_PERMISSIVE_MODIFY_CONTROL, false)); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, mods, requestControls); assertEquals(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 { 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"); LDAPAttribute attr = newLDAPAttribute("givenName", "Foo"); List<RawModification> mods = newRawModifications(delete(attr)); List<Control> requestControls = new ArrayList<>(); requestControls.add( new LDAPControl(ServerConstants.OID_PERMISSIVE_MODIFY_CONTROL, false)); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, mods, requestControls); assertEquals(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 { 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"); LDAPAttribute attr = new LDAPAttribute("description"); List<RawModification> mods = newRawModifications(delete(attr)); List<Control> requestControls = new ArrayList<>(); requestControls.add( new LDAPControl(ServerConstants.OID_PERMISSIVE_MODIFY_CONTROL, false)); ModifyOperation modifyOperation = processModify("uid=test.user," + baseDN, mods, requestControls); assertEquals(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 { TestCaseUtils.addEntry( "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 { TestCaseUtils.addEntry( "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 { String dn = "uid=testPassword03.user," + baseDN; Entry e = TestCaseUtils.addEntry( "dn: " + dn, "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "displayName: Test User", "userPassword: password"); List<Attribute> attrList = e.getAttribute(DirectoryServer.getAttributeTypeOrDefault("userpassword")); assertNotNull(attrList); String passwd = null; for (Attribute a : attrList) { for (ByteString v : a) { passwd = v.toString(); } } assertNotNull(passwd); String path = TestCaseUtils.createTempFile( "dn: " + dn, "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<Attribute> 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<Attribute> 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<Attribute> 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<Attribute> 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"; ByteString value = ByteString.wrap(Base64.decode(certificateValue)); LDAPAttribute attr = new LDAPAttribute("usercertificate", value); 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<Attribute> attrList = e.getAttribute(DirectoryServer.getAttributeTypeOrDefault("usercertificate")); 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()), 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.clearBackend("userRoot", baseDN); TestCaseUtils.addEntry("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<RawModification> mods = newRawModifications(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. TestCaseUtils.addEntry("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). TestCaseUtils.addEntry("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); } } }