TestModifyDNOperation.java revision 9aa1482c49865483f798f91ef7d16f03cc3ec811
/*
* 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
* 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-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2015 ForgeRock AS.
* Portions copyright 2013 Manuel Gaupp
*/
@SuppressWarnings("javadoc")
public class TestModifyDNOperation extends OperationTestCase
{
private InternalClientConnection proxyUserConn;
{
// Add the example.com entry
"dn: dc=example,dc=com",
"objectclass: top",
"objectclass: domain",
"dc: example",
"aci: (targetattr=\"*\")(version 3.0; acl \"Proxy Rights\"; " +
"allow(proxy) userdn=\"ldap:///uid=proxy.user,o=test\";)"
);
// Add the people entry
"dn: ou=People,dc=example,dc=com",
"objectclass: top",
"objectclass: organizationalUnit",
"ou: People"
);
// Add a test entry.
"dn: uid=user.0,ou=People,dc=example,dc=com",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"givenName: Aaccf",
"sn: Amar",
"cn: Aaccf Amar",
"initials: AQA",
"employeeNumber: 0",
"uid: user.0",
"mail: user.0@example.com",
"userPassword: password",
"telephoneNumber: 380-535-2354",
"homePhone: 707-626-3913",
"pager: 456-345-7750",
"mobile: 366-674-7274",
"street: 99262 Eleventh Street",
"l: Salem",
"st: NM",
"postalCode: 36530",
"postalAddress: Aaccf Amar$99262 Eleventh Street$Salem, NM 36530",
"description: This is the description for Aaccf Amar."
);
// Add a user capable of using the proxied authorization control.
"dn: uid=proxy.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: proxy.user",
"givenName: Proxy",
"sn: User",
"cn: Proxy User",
"userPassword: password",
"ds-privilege-name: bypass-acl",
"ds-privilege-name: proxied-auth");
}
/**
* Invokes a number of operation methods on the provided modify operation
* for which all processing has been completed. This method is used for
* tests that bypass the referential integrity plugin for whatever reason.
*
* @param modifyDNOperation The operation to be tested.
*/
private void
{
// assertEquals(InvocationCounterPlugin.getPreParseCount(), 1);
// assertEquals(InvocationCounterPlugin.getPreOperationCount(), 1);
// assertEquals(InvocationCounterPlugin.getPostOperationCount(), 1);
// assertEquals(InvocationCounterPlugin.getPostResponseCount(), 1);
}
/**
* Invokes a number of operation methods on the provided modify operation
* for which all processing has been completed. The counters
* postResponseCount and preParseCount are incremented twice when
* referential integrity plugin is enabled.
*
* @param modifyDNOperation The operation to be tested.
*/
{
// assertEquals(InvocationCounterPlugin.getPreParseCount(), 2);
// assertEquals(InvocationCounterPlugin.getPreOperationCount(), 1);
// assertEquals(InvocationCounterPlugin.getPostOperationCount(), 1);
// assertEquals(InvocationCounterPlugin.getPostResponseCount(), 2);
}
/**
* Invokes a number of operation methods on the provided modify operation
* for which the pre-operation plugin was not called.
*
* @param modifyDNOperation The operation to be tested.
*/
{
// assertEquals(InvocationCounterPlugin.getPreParseCount(), 1);
// assertEquals(InvocationCounterPlugin.getPreOperationCount(), 0);
// assertEquals(InvocationCounterPlugin.getPostOperationCount(), 1);
// assertEquals(InvocationCounterPlugin.getPostResponseCount(), 1);
}
/**
* Invokes a number of operation methods on the provided modify operation
* for which an error was found during parsing.
*
* @param modifyDNOperation The operation to be tested.
*/
{
// assertEquals(InvocationCounterPlugin.getPreParseCount(), 1);
// assertEquals(InvocationCounterPlugin.getPreOperationCount(), 0);
// assertEquals(InvocationCounterPlugin.getPostOperationCount(), 0);
// assertEquals(InvocationCounterPlugin.getPostResponseCount(), 1);
}
{
return new ModifyDNOperation[] {
};
}
private ModifyDNOperation runModifyDNOperation(
{
return op;
}
private ModifyDNOperation runModifyDNOperationRaw(
{
return op;
}
{
}
{
}
private ModifyDNOperation runModifyDNOperation(
InternalClientConnection conn, String entryDN, String newRDN, boolean deleteOldRDN, Control control) throws DirectoryException
{
return op;
}
private ModifyDNOperation runModifyDNOperationRaw(
{
ModifyDNOperation op = new ModifyDNOperationBasis(proxyUserConn, nextOperationID(), nextMessageID(),
return op;
}
private ByteString b(String s)
{
}
{
}
{
}
throws DirectoryException
{
{
}
}
@Test
public void testRawModify() throws Exception
{
ModifyDNOperation modifyDNOperation = runModifyDNOperationRaw(oldEntryDN, "uid=user.test0", false, null);
}
@Test
public void testProcessedModify() throws Exception
{
ModifyDNOperation modifyDNOperation = runModifyDNOperation(oldEntryDN, "uid=user.test0", false, null);
}
/**
* Test if it's possible to modify an rdn to a value that matches the current value
* by changing the case of some characters.
*/
@Test
public void testModifySameDN() throws Exception
{
}
/** Add another attribute to the RDN and change case of the existing value. */
@Test
public void testModifyDNchangeCaseAndAddValue() throws Exception
{
"dn: uid=userid.0,ou=People,dc=example,dc=com",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: userid.0",
"givenName: Babs",
"sn: Jensen",
"cn: Babs Jensen");
ModifyDNOperation modifyDNOperation = runModifyDNOperation(oldEntryDN, "uid=UserID.0+cn=Test", false, null);
}
throws DirectoryException
{
}
{
// Because deleteOldRDN is true, the values from RDN and the entry have to be identical
}
/**
* Add a value to the RDN which is already part of the entry, but with another string representation.
*/
@Test
public void testModifyDNchangeCaseOfExistingEntryValue() throws Exception
{
"dn: uid=userid.0,ou=People,dc=example,dc=com",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: userid.0",
"givenName: Babs",
"sn: Jensen",
"cn: Babs Jensen");
ModifyDNOperation modifyDNOperation = runModifyDNOperation(oldEntryDN, "uid=userid.0+sn=JENSEN", false, null);
}
{
}
@Test
public void testRawDeleteOldRDNModify() throws Exception
{
ModifyDNOperation modifyDNOperation = runModifyDNOperationRaw(oldEntryDN, "uid=user.test0", true, null);
}
@Test
public void testProcessedDeleteOldRDNModify() throws Exception
{
ModifyDNOperation modifyDNOperation = runModifyDNOperation(oldEntryDN, "uid=user.test0", true, null);
CancelRequest cancelRequest = new CancelRequest(false, LocalizableMessage.raw("testCancelBeforeStartup"));
}
@Test
public void testRawNewSuperiorModify() throws Exception
{
modifyDNOperation = runModifyDNOperationRaw(newEntryDN, "uid=user.0", true, "ou=People,dc=example,dc=com");
}
@Test
public void testProcessedNewSuperiorModify() throws Exception
{
ModifyDNOperation modifyDNOperation = runModifyDNOperation(oldEntryDN, "uid=user.test0", true, "dc=example,dc=com");
modifyDNOperation = runModifyDNOperation(newEntryDN, "uid=user.0", true, "ou=People,dc=example,dc=com");
}
@Test
public void testRawRDNModify() throws Exception
{
modifyDNOperation = runModifyDNOperation(newEntryDN, "uid=user.0", false, "ou=People,dc=example,dc=com");
{
}
}
{
{
}
return entry;
}
@Test
public void testInvalidEntryModify() throws Exception
{
"uid=user.invalid,ou=People,dc=example,dc=com", "uid=user.test0", true, "dc=example,dc=com");
}
@Test
public void testInvalidRDNModify() throws Exception
{
"uid=user.0,ou=People,dc=example,dc=com", "invalid=invalid", true, "dc=example,dc=com");
}
@Test
public void testInvalidSuperiorModify() throws Exception
{
"uid=user.0,ou=People,dc=example,dc=com", "uid=user.test0", true, "dc=invalid,dc=com");
}
@Test
public void testRawNoSuchDNModify() throws Exception
{
}
@Test
public void testRawNoSuchRDNModify() throws Exception
{
runModifyDNOperationRaw("uid=user.0,ou=People,dc=example,dc=com", "invalid RDN", true, "dc=example,dc=com");
}
@Test
public void testRawInvalidSuperiorModify() throws Exception
{
runModifyDNOperationRaw("uid=user.0,ou=People,dc=example,dc=com", "uid=user.test0", true, "invalid superior");
}
@Test
public void testModifySuffix() throws Exception
{
ModifyDNOperation modifyDNOperation = runModifyDNOperation("dc=example,dc=com", "dc=exampletest", true, null);
}
@Test
public void testRawProxyAuthV1Modify() throws Exception
{
ProxiedAuthV1Control authV1Control = new ProxiedAuthV1Control(b("cn=Directory Manager,cn=Root DNs,cn=config"));
ModifyDNOperation modifyDNOperation = runModifyDNOperationRaw(oldEntryDN, "uid=user.test0", false, null, authV1Control);
}
@Test
public void testProcessedProxyAuthV1Modify() throws Exception
{
ProxiedAuthV1Control authV1Control = new ProxiedAuthV1Control(b("cn=Directory Manager,cn=Root DNs,cn=config"));
modifyDNOperation = runModifyDNOperation(proxyUserConn, newEntryDN, "uid=user.0", true, authV1Control);
}
@Test
public void testProcessedProxyAuthV1DeniedModify() throws Exception
{
runModifyDNOperation(proxyUserConn, "uid=user.0,ou=People,dc=example,dc=com", "uid=user.test0", false, authV1Control);
}
@Test
public void testProcessedProxyAuthV2Modify() throws Exception
{
ProxiedAuthV2Control authV2Control = new ProxiedAuthV2Control(b("dn:cn=Directory Manager,cn=Root DNs,cn=config"));
modifyDNOperation = runModifyDNOperation(proxyUserConn, newEntryDN, "uid=user.0", true, authV2Control);
}
@Test
public void testProcessedProxyAuthV2DeniedModify() throws Exception
{
runModifyDNOperation(proxyUserConn, "uid=user.0,ou=People,dc=example,dc=com", "uid=user.test0", false, authV2Control);
}
@Test
public void testProcessedProxyAuthV2CriticalityModify() throws Exception
{
runModifyDNOperation(proxyUserConn, "uid=user.0,ou=People,dc=example,dc=com", "uid=user.test0", false, authV2Control);
}
@Test
public void testProcessedUnsupportedControlModify() throws Exception
{
ModifyDNOperation modifyDNOperation = runModifyDNOperation(getRootConnection(), "uid=user.0,ou=People,dc=example,dc=com", "uid=user.test0", false, assertControl);
}
@Test
public void testShortCircuitModify() throws Exception
{
// Since we are going to be watching the post-response count, we need to
// wait for the server to become idle before kicking off the next request to
// ensure that any remaining post-response processing from the previous
// operation has completed.
// Establish a connection to the server.
{
LDAPWriter w = new LDAPWriter(s);
BindRequestProtocolOp bindRequest = new BindRequestProtocolOp(b("cn=Directory Manager"), 3, b("password"));
bindMessage = r.readMessage();
w.writeMessage(message);
message = r.readMessage();
// assertEquals(InvocationCounterPlugin.waitForPostResponse(), 1);
}
}
public void testWriteLockModify() throws Exception
{
// We need the operation to be run in a separate thread because we are going
// to write lock the entry in the test case thread and check that the
// modify DN operation does not proceed.
// Establish a connection to the server.
{
LDAPWriter w = new LDAPWriter(s);
BindRequestProtocolOp bindRequest = new BindRequestProtocolOp(b("cn=Directory Manager"), 3, b("password"));
w.writeMessage(message);
message = r.readMessage();
// Since we are going to be watching the post-response count, we need to
// wait for the server to become idle before kicking off the next request
// to ensure that any remaining post-response processing from the previous
// operation has completed.
try
{
//long modifyDNRequests = ldapStatistics.getModifyDNRequests();
//long modifyDNResponses = ldapStatistics.getModifyDNResponses();
w.writeMessage(message);
message = r.readMessage();
// assertEquals(InvocationCounterPlugin.getPreParseCount(), 1);
// assertEquals(InvocationCounterPlugin.getPreOperationCount(), 0);
// assertEquals(InvocationCounterPlugin.getPostOperationCount(), 0);
// // The post response might not have been called yet.
// assertEquals(InvocationCounterPlugin.waitForPostResponse(), 1);
// assertEquals(ldapStatistics.getModifyDNRequests(), modifyDNRequests+1);
// assertEquals(ldapStatistics.getModifyDNResponses(),
// modifyDNResponses+1);
} finally
{
}
}
}
/**
* Tests performing a modify DN operation in which the new RDN contains an
* attribute type marked OBSOLETE in the server schema.
*/
@Test
public void testModifyDNWithObsoleteAttribute()
throws Exception
{
"dn: cn=schema",
"changetype: modify",
"add: attributeTypes",
"attributeTypes: ( testmodifydnwithobsoleteattribute-oid " +
"NAME 'testModifyDNWithObsoleteAttribute' OBSOLETE " +
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE " +
"X-ORGIN 'SchemaBackendTestCase' )");
{
"-h", "127.0.0.1",
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
"dn: cn=oldrdn,o=test",
"changetype: add",
"objectClass: top",
"objectClass: device",
"objectClass: extensibleObject",
"cn: oldrdn",
"",
"dn: cn=oldrdn,o=test",
"changetype: moddn",
"newRDN: testModifyDNWithObsoleteAttribute=foo",
"deleteOldRDN: 0"
);
{
"-h", "127.0.0.1",
"-D", "cn=Directory Manager",
"-w", "password",
"-f", path
};
}
/**
* Tests a subtree rename operation to ensure that subordinate modify DN
* plugins will be invoked as expected.
*/
@Test
public void testSubordinateModifyDNPluginsForSubtreeRename()
throws Exception
{
try
{
"dn: ou=People,dc=example,dc=com",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People",
"",
"dn: uid=first.test,ou=People,dc=example,dc=com",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: first.test",
"givenName: First",
"sn: Test",
"cn: First Test",
"userPassword: Password",
"ou: People",
"",
"dn: uid=second.test,ou=People,dc=example,dc=com",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: second.test",
"givenName: Second",
"sn: Test",
"cn: Second Test",
"userPassword: Password");
dn("uid=first.test,ou=People,dc=example,dc=com")));
dn("uid=first.test,ou=Users,dc=example,dc=com")));
// assertEquals(InvocationCounterPlugin.getSubordinateModifyDNCount(), 2);
dn("uid=first.test,ou=People,dc=example,dc=com")));
dn("uid=first.test,ou=Users,dc=example,dc=com")));
}
finally
{
// Other tests in this class rely on a predefined structure, so we need to
// make sure to put it back to the way it should be.
setUp();
}
}
/**
* Tests a subtree move operation to ensure that subordinate modify DN
* plugins will be invoked as expected.
*/
@Test
public void testSubordinateModifyDNPluginsForSubtreeMove()
throws Exception
{
try
{
"dn: ou=Org 1,dc=example,dc=com",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: Org 1",
"",
"dn: ou=Org 2,dc=example,dc=com",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: Org 2",
"",
"dn: ou=Org 1.1,ou=Org 1,dc=example,dc=com",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: Org 1.1",
"",
"dn: uid=first.test,ou=Org 1.1,ou=Org 1,dc=example,dc=com",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: first.test",
"givenName: First",
"sn: Test",
"cn: First Test",
"userPassword: Password",
"ou: Org 1.1",
"",
"dn: uid=second.test,ou=Org 1.1,ou=Org 1,dc=example,dc=com",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: second.test",
"givenName: Second",
"sn: Test",
"cn: Second Test",
"userPassword: Password");
dn("uid=first.test,ou=Org 1.1,ou=Org 1,dc=example,dc=com")));
dn("uid=first.test,ou=Org 2.1,ou=Org 2,dc=example,dc=com")));
"ou=Org 2.1", true,
"ou=Org 2,dc=example,dc=com");
// assertEquals(InvocationCounterPlugin.getSubordinateModifyDNCount(), 2);
dn("uid=first.test,ou=Org 1.1,ou=Org 1,dc=example,dc=com")));
dn("uid=first.test,ou=Org 2.1,ou=Org 2,dc=example,dc=com")));
}
finally
{
// Other tests in this class rely on a predefined structure, so we need to
// make sure to put it back to the way it should be.
setUp();
}
}
@Test
public void testCancelBeforeStartup() throws Exception
{
"uid=user.invalid,ou=People,dc=example,dc=com", "uid=user.test0", true, "dc=example,dc=com");
}
/**
* Tests whether an invalid rdn is allowed during an modrdn operation.
* This test uses a valid attribute type with an empty value.
*
* @throws Exception
*/
public void testInvalidModRDN() throws Exception
{
+"/dc=example,dc=com";
/* Create the initial context */
try
{
"uid=,ou=People,dc=example,dc=com");
}
finally
{
/* Close the context when it's done */
}
}
}