From a1ac9881ff274fe6f797743b3df25c8905de9c7a Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Wed, 03 Sep 2014 08:48:57 +0000
Subject: [PATCH] Checkpoint commit for OPENDJ-1206 : Create a new ReplicationBackend/ChangelogBackend to support cn=changelog
---
opends/tests/unit-tests-testng/src/server/org/opends/server/backends/ChangelogBackendTestCase.java | 183 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 176 insertions(+), 7 deletions(-)
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/ChangelogBackendTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/ChangelogBackendTestCase.java
index 01eff69..fdade65 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/ChangelogBackendTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/ChangelogBackendTestCase.java
@@ -40,9 +40,11 @@
import org.opends.server.api.Backend;
import org.opends.server.backends.ChangelogBackend.SearchParams;
import org.opends.server.controls.ExternalChangelogRequestControl;
+import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.ModifyDNOperationBasis;
+import org.opends.server.core.ModifyOperation;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchListener;
@@ -199,7 +201,7 @@
@Override
public boolean isECLEnabledDomain(DN baseDN)
{
- return baseDN.equals(DN_OTEST) || baseDN.equals(DN_OTEST2) || baseDN.equals(DN_OTEST3);
+ return baseDN.toString().startsWith("o=test");
}
});
debugInfo("configure", "ReplicationServer created:" + replicationServer);
@@ -310,7 +312,7 @@
debugInfo(test, "Ending search with success");
}
- @Test(enabled=false)
+ @Test
public void searchInCookieModeAfterDomainIsRemoved() throws Exception
{
String test = "CookieAfterDomainIsRemoved";
@@ -350,7 +352,7 @@
* one suffix if run before them, so it is necessary to add them as
* dependencies.
*/
- @Test(enabled=false, dependsOnMethods = {
+ @Test(enabled=true, dependsOnMethods = {
"searchInCookieModeOnOneSuffixUsingEmptyCookie",
"searchInCookieModeOnOneSuffix",
"searchInCookieModeAfterDomainIsRemoved",
@@ -477,13 +479,13 @@
}
}
- @Test(enabled=false, dependsOnMethods = { "searchInCookieModeOnTwoSuffixes" })
+ @Test(enabled=true, dependsOnMethods = { "searchInCookieModeOnTwoSuffixes" })
public void searchInCookieModeOnTwoSuffixesWithPrivateBackend() throws Exception
{
String test = "CookiePrivateBackend";
debugInfo(test, "Starting test");
- // Use o=test3 to avoid collision with o=test2 used by searchInCookieModeOnTwoSuffixes test
+ // Use o=test3 to avoid collision with o=test2 already used by a previous test
Backend<?> backend3 = null;
Pair<ReplicationBroker,LDAPReplicationDomain> replication1 = null;
LDAPReplicationDomain domain2 = null;
@@ -620,7 +622,149 @@
public void simultaneousPersistentSearches() throws Exception
{
// TODO
- // see testECLAfterDomainIsRemoved
+ // see FullTestSimultaneousPersistentSearches
+ }
+
+ @Test(enabled=true, dependsOnMethods = { "searchInCookieModeOnTwoSuffixesWithPrivateBackend"})
+ public void searchInCookieModeUseOfIncludeAttributes() throws Exception
+ {
+ String test = "IncludeAttributes";
+ debugInfo(test, "Starting test\n\n");
+
+ // Use o=test4 and o=test5 to avoid collision with existing suffixes already used by previous test
+ final String backendId4 = "test4";
+ final DN baseDN4 = DN.decode("o=" + backendId4);
+ final String backendId5 = "test5";
+ final DN baseDN5 = DN.decode("o=" + backendId5);
+ Backend<?> backend4 = null;
+ Backend<?> backend5 = null;
+ LDAPReplicationDomain domain4 = null;
+ LDAPReplicationDomain domain5 = null;
+ LDAPReplicationDomain domain41 = null;
+ try
+ {
+ SortedSet<String> replServers = newSortedSet("localhost:" + replicationServerPort);
+
+ // backend4 and domain4
+ backend4 = initializeMemoryBackend(false, backendId4);
+ DomainFakeCfg domainConf = new DomainFakeCfg(baseDN4, 1702, replServers);
+ SortedSet<String> eclInclude = newSortedSet("sn", "roomnumber");
+ domain4 = startNewReplicationDomain(domainConf, eclInclude, eclInclude);
+
+ // backend5 and domain5
+ backend5 = initializeMemoryBackend(false, backendId5);
+ domainConf = new DomainFakeCfg(baseDN5, 1703, replServers);
+ eclInclude = newSortedSet("objectclass");
+ SortedSet<String> eclIncludeForDeletes = newSortedSet("*");
+ domain5 = startNewReplicationDomain(domainConf, eclInclude, eclIncludeForDeletes);
+
+ // domain41
+ domainConf = new DomainFakeCfg(baseDN4, 1704, replServers);
+ eclInclude = newSortedSet("cn");
+ domain41 = startNewReplicationDomain(domainConf, eclInclude, eclInclude);
+
+ Thread.sleep(1000);
+
+ addEntry(createEntry(baseDN4));
+ addEntry(createEntry(baseDN5));
+
+ Entry uentry1 = entryFromLdifString(makeLdif(
+ "dn: cn=Fiona Jensen,o=" + backendId4,
+ "objectclass: top",
+ "objectclass: person",
+ "objectclass: organizationalPerson",
+ "objectclass: inetOrgPerson",
+ "cn: Fiona Jensen",
+ "sn: Jensen",
+ "uid: fiona",
+ "telephonenumber: 12121212"));
+ addEntry(uentry1);
+
+ Entry uentry2 = entryFromLdifString(makeLdif(
+ "dn: cn=Robert Hue,o=" + backendId5,
+ "objectclass: top",
+ "objectclass: person",
+ "objectclass: organizationalPerson",
+ "objectclass: inetOrgPerson",
+ "cn: Robert Hue",
+ "sn: Robby",
+ "uid: robert",
+ "telephonenumber: 131313"));
+ addEntry(uentry2);
+
+ // mod 'sn' of fiona with 'sn' configured as ecl-incl-att
+ final ModifyOperation modOp1 = connection.processModify(uentry1.getDN(), createAttributeModif("sn", "newsn"));
+ waitForSearchOpResult(modOp1, ResultCode.SUCCESS);
+
+ // mod 'telephonenumber' of robert
+ final ModifyOperation modOp2 = connection.processModify(uentry2.getDN(),
+ createAttributeModif("telephonenumber", "555555"));
+ waitForSearchOpResult(modOp2, ResultCode.SUCCESS);
+
+ // moddn robert to robert2
+ ModifyDNOperation modDNOp = connection.processModifyDN(
+ DN.decode("cn=Robert Hue," + baseDN5),
+ RDN.decode("cn=Robert Hue2"), true,
+ baseDN5);
+ waitForSearchOpResult(modDNOp, ResultCode.SUCCESS);
+
+ // del robert
+ final DeleteOperation delOp = connection.processDelete(DN.decode("cn=Robert Hue2," + baseDN5));
+ waitForSearchOpResult(delOp, ResultCode.SUCCESS);
+
+ // Search on all suffixes
+ String cookie = "";
+ InternalSearchOperation searchOp = searchChangelogUsingCookie("(targetDN=*)", cookie, 8, SUCCESS, test);
+
+ for (SearchResultEntry resultEntry : searchOp.getSearchEntries())
+ {
+ String targetdn = getAttributeValue(resultEntry, "targetdn");
+
+ if (targetdn.endsWith("cn=robert hue,o=" + backendId5)
+ || targetdn.endsWith("cn=robert hue2,o=" + backendId5))
+ {
+ Entry targetEntry = parseIncludedAttributes(resultEntry, targetdn);
+
+ Set<String> eoc = newSet("person", "inetOrgPerson", "organizationalPerson", "top");
+ assertAttributeValues(targetEntry, "objectclass", eoc);
+
+ String changeType = getAttributeValue(resultEntry, "changetype");
+ if ("delete".equals(changeType))
+ {
+ // We are using "*" for deletes so should get back 4 attributes.
+ assertThat(targetEntry.getAttributes()).hasSize(4);
+ assertAttributeValue(targetEntry, "uid", "robert");
+ assertAttributeValue(targetEntry, "cn", "Robert Hue2");
+ assertAttributeValue(targetEntry, "telephonenumber", "555555");
+ assertAttributeValue(targetEntry, "sn", "Robby");
+ }
+ else
+ {
+ assertThat(targetEntry.getAttributes()).isEmpty();
+ }
+ }
+ else if (targetdn.endsWith("cn=fiona jensen,o=" + backendId4))
+ {
+ Entry targetEntry = parseIncludedAttributes(resultEntry, targetdn);
+
+ assertThat(targetEntry.getAttributes()).hasSize(2);
+ assertAttributeValue(targetEntry,"sn","jensen");
+ assertAttributeValue(targetEntry,"cn","Fiona Jensen");
+ }
+ assertAttributeValue(resultEntry,"changeinitiatorsname", "cn=Internal Client,cn=Root DNs,cn=config");
+ }
+ }
+ finally
+ {
+ final DN fionaDN = DN.decode("cn=Fiona Jensen,o=" + backendId4);
+ waitForSearchOpResult(connection.processDelete(fionaDN), ResultCode.SUCCESS);
+ waitForSearchOpResult(connection.processDelete(baseDN4), ResultCode.SUCCESS);
+ waitForSearchOpResult(connection.processDelete(baseDN5), ResultCode.SUCCESS);
+
+ removeReplicationDomains(domain41, domain4, domain5);
+ removeBackend(backend4, backend5);
+ }
+ debugInfo(test, "Ending test with success");
}
// TODO : other tests methods in ECLTest
@@ -1254,6 +1398,21 @@
.isEqualTo(expected);
}
+ private static void assertAttributeValues(Entry entry, String attrName, Set<String> expectedValues)
+ {
+ final Set<String> values = new HashSet<String>();
+ for (Attribute attr : entry.getAttribute(attrName))
+ {
+ for (AttributeValue value : attr)
+ {
+ values.add(value.toString());
+ }
+ }
+ assertThat(values)
+ .as("In entry " + entry + " incorrect values for attribute '" + attrName + "'")
+ .isEqualTo(expectedValues);
+ }
+
private static void assertAttributeValue(Entry entry, String attrName, String expectedValue)
{
assertFalse(expectedValue.contains("\n"),
@@ -1315,7 +1474,6 @@
return results;
}
- // TODO : share this code with other classes
private static String getAttributeValue(Entry entry, String attrName)
{
List<Attribute> attrs = entry.getAttribute(attrName.toLowerCase());
@@ -1328,6 +1486,17 @@
return av.toString();
}
+ private Entry parseIncludedAttributes(SearchResultEntry resultEntry, String targetdn) throws Exception
+ {
+ // Parse includedAttributes as an entry.
+ String includedAttributes = getAttributeValue(resultEntry, "includedattributes");
+ String[] ldifAttributeLines = includedAttributes.split("\\n");
+ String[] ldif = new String[ldifAttributeLines.length + 1];
+ System.arraycopy(ldifAttributeLines, 0, ldif, 1, ldifAttributeLines.length);
+ ldif[0] = "dn: " + targetdn;
+ return TestCaseUtils.makeEntry(ldif);
+ }
+
private void debugAndWriteEntries(LDIFWriter ldifWriter,List<SearchResultEntry> entries, String tn) throws Exception
{
if (entries != null)
--
Gitblit v1.10.0