/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2006-2009 Sun Microsystems, Inc. * Portions Copyright 2011-2013 ForgeRock AS */ package org.opends.server.backends.jeb; import java.util.*; import org.opends.server.TestCaseUtils; import org.opends.server.admin.std.server.LocalDBBackendCfg; import org.opends.server.admin.std.meta.LocalDBBackendCfgDefn; import org.opends.server.admin.server.AdminTestCaseUtils; import org.opends.server.controls.SubtreeDeleteControl; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.DirectoryServer; import org.opends.server.protocols.internal.InternalClientConnection; import org.opends.server.protocols.internal.InternalSearchOperation; import org.opends.server.protocols.ldap.LDAPFilter; import org.opends.server.types.*; import org.opends.server.util.Base64; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.annotations.BeforeClass; import org.testng.annotations.AfterClass; import static org.testng.Assert.*; import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.LockMode; import org.opends.server.core.DeleteOperationBasis; import org.opends.server.core.ModifyOperationBasis; /** * BackendImpl Tester. */ public class TestBackendImpl extends JebTestCase { private String homeDirName; private BackendImpl backend; private List<Entry> topEntries; private List<Entry> entries; private List<Entry> additionalEntries; private Entry replaceEntry; private Entry newTop; /** * The attribute used to return a search index debug string to the client. */ public static final String ATTR_DEBUG_SEARCH_INDEX = "debugsearchindex"; @BeforeClass public void setUp() throws Exception { // This test suite depends on having the schema available, so we'll make // sure the server is started. TestCaseUtils.startServer(); TestCaseUtils.enableBackend("indexRoot"); homeDirName = "db_index_test"; backend = (BackendImpl)DirectoryServer.getBackend("indexRoot"); topEntries = TestCaseUtils.makeEntries( "dn: dc=test,dc=com", "objectclass: top", "objectclass: domain", "dc: example", "", "dn: ou=People,dc=test,dc=com", "objectclass: top", "objectclass: organizationalUnit", "ou: People", "", "dn: dc=test1,dc=com", "objectclass: top", "objectclass: domain", "dc: example1"); entries = TestCaseUtils.makeEntries( "dn: uid=user.0,ou=People,dc=test,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.", "", "dn: uid=user.1,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Aaren", "givenName;lang-fr: test2", "givenName;lang-cn: test2", "givenName;lang-es: test3", "sn: Atp", "cn: Aaren Atp", "initials: APA", "employeeNumber: 1", "uid: user.1", "mail: user.1@example.com", "userPassword: password", "telephoneNumber: 643-278-6134", "homePhone: 546-786-4099", "pager: 508-261-3187", "mobile: 377-267-7824", "carLicense: 377-267-7824", "street: 78113 Fifth Street", "l: Chico", "st: TN", "postalCode: 72322", "postalAddress: Aaren Atp$78113 Fifth Street$Chico, TN 72322", "description: This is the description for Aaren Atp.", "", "dn: uid=user.2,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Aarika", "sn: Atpco", "cn: Aarika Atpco", "initials: ARA", "employeeNumber: 2", "uid: user.2", "mail: user.2@example.com", "userPassword: password", "telephoneNumber: 547-504-3498", "homePhone: 955-899-7308", "pager: 710-832-9316", "mobile: 688-388-4525", "carLicense: 688-388-4525", "street: 59208 Elm Street", "l: Youngstown", "st: HI", "postalCode: 57377", "postalAddress: Aarika Atpco$59208 Elm Street$Youngstown, HI 57377", "description: This is the description for Aarika Atpco.", "", "dn: uid=user.3,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Aaron", "sn: Atrc", "cn: Aaron Atrc", "initials: AIA", "employeeNumber: 3", "uid: user.3", "mail: user.3@example.com", "userPassword: password", "telephoneNumber: 128-108-4939", "homePhone: 512-782-9966", "pager: 322-646-5118", "mobile: 360-957-9137", "carLicense: 360-957-9137", "street: 25074 Hill Street", "l: Toledo", "st: OR", "postalCode: 55237", "postalAddress: Aaron Atrc$25074 Hill Street$Toledo, OR 55237", "description: This is the description for Aaron Atrc.", "", "dn: uid=user.4,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Aartjan", "sn: Aalders", "cn: Aartjan Aalders", "initials: ALA", "employeeNumber: 4", "uid: user.4", "mail: user.4@example.com", "userPassword: password", "telephoneNumber: 981-148-3303", "homePhone: 196-877-2684", "pager: 910-998-4607", "mobile: 123-239-8262", "carLicense: 123-239-8262", "street: 81512 Sunset Street", "l: Chattanooga", "st: WV", "postalCode: 29530", "postalAddress: Aartjan Aalders$81512 Sunset Street$Chattanooga, WV 29530", "description: This is the description for Aartjan Aalders.", "", "dn: uid=user.5,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Abagael", "sn: Aasen", "cn: Abagael Aasen", "initials: AKA", "employeeNumber: 5", "uid: user.5", "mail: user.5@example.com", "userPassword: password", "telephoneNumber: 930-493-2391", "homePhone: 078-254-3960", "pager: 281-936-8197", "mobile: 559-822-7712", "carLicense: 559-822-7712", "street: 31988 Central Street", "l: Chico", "st: MS", "postalCode: 20135", "postalAddress: Abagael Aasen$31988 Central Street$Chico, MS 20135", "description: This is the description for Abagael Aasen.", "", "dn: uid=user.6,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Abagail", "sn: Abadines", "cn: Abagail Abadines", "initials: AQA", "employeeNumber: 6", "uid: user.6", "mail: user.6@example.com", "userPassword: password", "telephoneNumber: 110-761-3861", "homePhone: 459-123-0553", "pager: 799-151-2688", "mobile: 953-582-7252", "carLicense: 953-582-7252", "street: 60100 Dogwood Street", "l: Hartford", "st: NE", "postalCode: 79353", "postalAddress: Abagail Abadines$60100 Dogwood Street$Hartford, NE 79353", "description: This is the description for Abagail Abadines.", "", "dn: uid=user.7,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Abahri", "sn: Abazari", "cn: Abahri Abazari", "initials: AXA", "employeeNumber: 7", "uid: user.7", "mail: user.7@example.com", "userPassword: password", "telephoneNumber: 594-537-4292", "homePhone: 174-724-6390", "pager: 733-217-8194", "mobile: 879-706-0172", "carLicense: 879-706-0172", "street: 77693 Oak Street", "l: Philadelphia", "st: MN", "postalCode: 78550", "postalAddress: Abahri Abazari$77693 Oak Street$Philadelphia, MN 78550", "description: This is the description for Abahri Abazari.", "", "dn: uid=user.8,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Abbas", "sn: Abbatantuono", "cn: Abbas Abbatantuono", "initials: AVA", "employeeNumber: 8", "uid: user.8", "mail: user.8@example.com", "userPassword: password", "telephoneNumber: 246-674-8407", "homePhone: 039-769-3372", "pager: 226-950-2371", "mobile: 587-709-2996", "carLicense: 587-709-2996", "street: 23230 Hill Street", "l: Little Rock", "st: AR", "", "dn: uid=user.9,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Abbe", "sn: Abbate", "cn: Abbe Abbate", "initials: AWA", "employeeNumber: 9", "uid: user.9", "mail: user.9@example.com", "userPassword: password", "telephoneNumber: 205-805-3357", "homePhone: 770-780-5917", "pager: 537-074-8005", "mobile: 120-204-7597", "carLicense: 120-204-7597", "street: 47952 Center Street", "l: Butte", "st: TN", "postalCode: 69384", "postalAddress: Abbe Abbate$47952 Center Street$Butte, TN 69384", "description: This is the description for Abbe Abbate.", "", "dn: uid=user.10,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Abbey", "sn: Abbie", "cn: Abbey Abbie", "initials: AZA", "employeeNumber: 10", "uid: user.10", "mail: user.10@example.com", "userPassword: password", "telephoneNumber: 457-819-0832", "homePhone: 931-305-5452", "pager: 118-165-7194", "mobile: 553-729-5572", "carLicense: 553-729-5572", "street: 54262 Highland Street", "l: Spartanburg", "st: PA", "postalCode: 38151", "postalAddress: Abbey Abbie$54262 Highland Street$Spartanburg, PA 38151", "description: This is the description for Abbey Abbie.", "", "dn: uid=user.539,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Ardyth", "sn: Bainton", "cn: Ardyth Bainton", "initials: AIB", "employeeNumber: 539", "uid: user.539", "mail: user.539@example.com", "userPassword: password", "telephoneNumber: 641-433-7404", "homePhone: 524-765-8780", "pager: 985-331-1308", "mobile: 279-423-0188", "carLicense: 279-423-0188", "street: 81170 Taylor Street", "l: Syracuse", "st: WV", "postalCode: 93507", "postalAddress: Ardyth Bainton$81170 Taylor Street$Syracuse, WV 93507", "description: This is the description for Ardyth Bainton.", "", "dn: uid=user.446,dc=test1,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Annalee", "sn: Avard", "cn: Annalee Avard", "initials: ANA", "employeeNumber: 446", "uid: user.446", "mail: user.446@example.com", "userPassword: password", "telephoneNumber: 875-335-2712", "homePhone: 181-995-6635", "pager: 586-905-4185", "mobile: 826-857-7592", "carLicense: 826-857-7592", "street: 46168 Mill Street", "l: Charleston", "st: CO", "postalCode: 60948", "postalAddress: Annalee Avard$46168 Mill Street$Charleston, CO 60948", "description: This is the description for Annalee Avard.", "", "dn: uid=user.362,dc=test1,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Andaree", "sn: Asawa", "cn: Andaree Asawa", "initials: AEA", "employeeNumber: 362", "uid: user.362", "mail: user.362@example.com", "userPassword: password", "telephoneNumber: 399-788-7334", "homePhone: 798-076-5683", "pager: 034-026-9411", "mobile: 948-743-9197", "carLicense: 948-743-9197", "street: 81028 Forest Street", "l: Wheeling", "st: IA", "postalCode: 60905", "postalAddress: Andaree Asawa$81028 Forest Street$Wheeling, IA 60905", "description: This is the description for Andaree Asawa."); replaceEntry = TestCaseUtils.makeEntry( "dn: uid=user.0,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Testing", "sn: Test", "cn: Testing Test", "initials: TT", "employeeNumber: 777", "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", "carLicense: 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."); additionalEntries = TestCaseUtils.makeEntries( "dn: uid=user.446,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Annalee", "sn: Avard", "cn: Annalee Avard", "initials: ANA", "employeeNumber: 446", "uid: user.446", "mail: user.446@example.com", "userPassword: password", "telephoneNumber: 875-335-2712", "homePhone: 181-995-6635", "pager: 586-905-4185", "mobile: 826-857-7592", "carLicense: 826-857-7592", "street: 46168 Mill Street", "l: Charleston", "st: CO", "postalCode: 60948", "postalAddress: Annalee Avard$46168 Mill Street$Charleston, CO 60948", "description: This is the description for Annalee Avard.", "", "dn: uid=user.362,ou=People,dc=test,dc=com", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "givenName: Andaree", "sn: Asawa", "cn: Andaree Asawa", "initials: AEA", "employeeNumber: 362", "uid: user.362", "mail: user.362@example.com", "userPassword: password", "telephoneNumber: 399-788-7334", "homePhone: 798-076-5683", "pager: 034-026-9411", "mobile: 948-743-9197", "carLicense: 948-743-9197", "street: 81028 Forest Street", "l: Wheeling", "st: IA", "postalCode: 60905", "postalAddress: Andaree Asawa$81028 Forest Street$Wheeling, IA 60905", "description: This is the description for Andaree Asawa."); newTop = TestCaseUtils.makeEntry( "dn: ou=JEB Testers,dc=test,dc=com", "objectclass: top", "objectclass: organizationalUnit", "ou: People" ); } @AfterClass public void cleanUp() throws Exception { TestCaseUtils.disableBackend("importRoot"); } @Test(expectedExceptions = DirectoryException.class) public void testAddNoParent() throws Exception { for (Entry entry : entries) { backend.addEntry(entry, null); } } @Test(dependsOnMethods = "testAddNoParent") public void testAdd() throws Exception { for (Entry topEntry : topEntries) { backend.addEntry(topEntry, null); assertNotNull(backend.getEntry(topEntry.getDN())); } for (Entry entry : entries) { backend.addEntry(entry, null); assertNotNull(backend.getEntry(entry.getDN())); } } @Test(dependsOnMethods = "testAdd") public void testSearchScope() throws Exception { InternalClientConnection conn = InternalClientConnection.getRootConnection(); InternalSearchOperation search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.BASE_OBJECT, LDAPFilter.decode("(objectClass=*)").toSearchFilter()); LinkedList<SearchResultEntry> result = search.getSearchEntries(); assertEquals(result.size(), 1); assertEquals(result.get(0).getDN().toString(), "dc=test,dc=com"); search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.BASE_OBJECT, LDAPFilter.decode("(ou=People)").toSearchFilter()); result = search.getSearchEntries(); assertEquals(result.size(), 0); search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.SINGLE_LEVEL, LDAPFilter.decode("(objectClass=*)").toSearchFilter()); result = search.getSearchEntries(); assertEquals(result.size(), 1); assertEquals(result.get(0).getDN().toString(), "ou=People,dc=test,dc=com"); search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.SUBORDINATE_SUBTREE, LDAPFilter.decode("(objectClass=*)").toSearchFilter()); result = search.getSearchEntries(); assertEquals(result.size(), 13); for (Entry entry : result) { assertNotSame(entry.getDN().toString(), "dc=test,dc=com"); } search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.WHOLE_SUBTREE, LDAPFilter.decode("(objectClass=*)").toSearchFilter()); result = search.getSearchEntries(); assertEquals(result.size(), 14); } @Test(dependsOnMethods = "testAdd") public void testNumSubordinates() throws Exception { DN dn = DN.decode("dc=test,dc=com"); assertEquals(backend.numSubordinates(dn, false), 1); assertEquals(backend.numSubordinates(dn, true), 13); dn = DN.decode("ou=People,dc=test,dc=com"); assertEquals(backend.numSubordinates(dn, false), 12); assertEquals(backend.numSubordinates(dn, true), 12); dn = DN.decode("dc=com"); assertEquals(backend.numSubordinates(dn, false), -1); assertEquals(backend.numSubordinates(dn, true), -1); dn = DN.decode("dc=test1,dc=com"); assertEquals(backend.numSubordinates(dn, false), 2); assertEquals(backend.numSubordinates(dn, true), 2); dn = DN.decode("uid=user.10,ou=People,dc=test,dc=com"); assertEquals(backend.numSubordinates(dn, false), 0); assertEquals(backend.numSubordinates(dn, true), 0); dn = DN.decode("uid=does not exist,ou=People,dc=test,dc=com"); assertEquals(backend.numSubordinates(dn, false), -1); assertEquals(backend.numSubordinates(dn, true), -1); } @Test(dependsOnMethods = "testAdd") public void testSearchIndex() throws Exception { InternalClientConnection conn = InternalClientConnection.getRootConnection(); LinkedHashSet<String> attribs = new LinkedHashSet<String>(); String debugString; int finalStartPos; int finalEndPos; int finalCount; InternalSearchOperation search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.WHOLE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, LDAPFilter.decode("(&(cn=Aaccf Amar)(cn=Ardyth Bainton))").toSearchFilter(), attribs); LinkedList<SearchResultEntry> result = search.getSearchEntries(); assertEquals(result.size(), 0); attribs.add(ATTR_DEBUG_SEARCH_INDEX); search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.WHOLE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, LDAPFilter.decode("(&(cn=Aaccf Amar)(employeeNumber=222))").toSearchFilter(), attribs); result = search.getSearchEntries(); //Only one index should be used because it is below the FILTER_CANDIDATEassertEquals(ec.getDN2URI().)_THRESHOLD. debugString = result.get(0).getAttribute("debugsearchindex").get(0).toString(); assertTrue(debugString.split("cn").length <= 3); finalStartPos = debugString.indexOf("final=") + 13; finalEndPos = debugString.indexOf("]", finalStartPos); finalCount = Integer.valueOf(debugString.substring(finalStartPos, finalEndPos)); assertEquals(finalCount, 1); search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.WHOLE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, LDAPFilter.decode("(|(cn=Aaccf Amar)(cn=Ardyth Bainton))").toSearchFilter(), attribs); result = search.getSearchEntries(); debugString = result.get(0).getAttribute("debugsearchindex").get(0).toString(); assertTrue(!debugString.contains("NOT-INDEXED")); finalStartPos = debugString.indexOf("final=") + 13; finalEndPos = debugString.indexOf("]", finalStartPos); finalCount = Integer.valueOf(debugString.substring(finalStartPos, finalEndPos)); assertEquals(finalCount, 2); search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.WHOLE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, LDAPFilter.decode("(&(employeeNumber=*)(cn=A*)(employeeNumber>=0)(employeeNumber<=z))").toSearchFilter(), attribs); result = search.getSearchEntries(); debugString = result.get(0).getAttribute("debugsearchindex").get(0).toString(); assertTrue(!debugString.contains("NOT-INDEXED")); finalStartPos = debugString.indexOf("final=") + 13; finalEndPos = debugString.indexOf("]", finalStartPos); finalCount = Integer.valueOf(debugString.substring(finalStartPos, finalEndPos)); assertEquals(finalCount, 12); search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.WHOLE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, LDAPFilter.decode("(&(employeeNumber<=z)(cn<=Abbey Abbie)(cn>=0)(|(cn>=Abahri Abazari)(employeeNumber<=9)))").toSearchFilter(), attribs); result = search.getSearchEntries(); debugString = result.get(0).getAttribute("debugsearchindex").get(0).toString(); assertTrue(!debugString.contains("NOT-INDEXED")); finalStartPos = debugString.indexOf("final=") + 13; finalEndPos = debugString.indexOf("]", finalStartPos); finalCount = Integer.valueOf(debugString.substring(finalStartPos, finalEndPos)); assertEquals(finalCount, 11); search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.WHOLE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, LDAPFilter.decode("(cn~=Aartjan)").toSearchFilter(), attribs); result = search.getSearchEntries(); debugString = result.get(0).getAttribute("debugsearchindex").get(0).toString(); assertTrue(!debugString.contains("NOT-INDEXED")); finalStartPos = debugString.indexOf("final=") + 13; finalEndPos = debugString.indexOf("]", finalStartPos); finalCount = Integer.valueOf(debugString.substring(finalStartPos, finalEndPos)); assertEquals(finalCount, 1); } @Test(dependsOnMethods = {"testAdd", "testSearchIndex", "testSearchScope", "testSearchNotIndexed", "testModifyDNNewSuperior", "testMatchedDN", "testNumSubordinates", "testNumSubordinatesIndexEntryLimitExceeded"}) public void testDeleteSubtree() throws Exception { Control control = new SubtreeDeleteControl(false); ArrayList<Control> deleteSubTreeControl = new ArrayList<Control>(); deleteSubTreeControl.add(control); InternalClientConnection conn = InternalClientConnection.getRootConnection(); DeleteOperationBasis delete = new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), deleteSubTreeControl, DN.decode("dc=test1,dc=com")); backend.deleteEntry(DN.decode("dc=test1,dc=com"), delete); EntryContainer ec = backend.getRootContainer().getEntryContainer(DN.decode("dc=test1,dc=com")); ec.sharedLock.lock(); try { assertFalse(ec.entryExists(DN.decode("dc=test1,dc=com"))); assertFalse(ec.entryExists(DN.decode("uid=user.362,dc=test1,dc=com"))); } finally { ec.sharedLock.unlock(); } } @Test(dependsOnMethods = {"testAdd", "testSearchIndex", "testSearchScope", "testMatchedDN"}) public void testDeleteEntry() throws Exception { ArrayList<Control> noControls = new ArrayList<Control>(0); InternalClientConnection conn = InternalClientConnection.getRootConnection(); Entry entry; EntryID entryID; AttributeType attribute; AttributeIndex index; HashSet<byte[]> addKeys; DatabaseEntry key; PresenceIndexer presenceIndexer; EqualityIndexer equalityIndexer; SubstringIndexer substringIndexer; OrderingIndexer orderingIndexer; EntryContainer ec = backend.getRootContainer().getEntryContainer(DN.decode("ou=People,dc=test,dc=com")); ec.sharedLock.lock(); try { entry = ec.getEntry(DN.decode("uid=user.539,ou=People,dc=test,dc=com")); entryID = ec.getDN2ID().get(null, DN.decode("uid=user.539,ou=People,dc=test,dc=com"), LockMode.DEFAULT); DeleteOperationBasis delete = new DeleteOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), noControls, DN.decode("uid=user.539,ou=People,dc=test,dc=com")); backend.deleteEntry(DN.decode("uid=user.539,ou=People,dc=test,dc=com"), delete); assertFalse(ec.entryExists(DN.decode("uid=user.539,ou=People,dc=test,dc=com"))); assertNull(ec.getDN2ID().get(null, DN.decode("uid=user.539,ou=People,dc=test,dc=com"), LockMode.DEFAULT)); assertFalse(ec.getDN2URI().delete(null, DN.decode("uid=user.539,ou=People,dc=test,dc=com"))); attribute = entries.get(0).getAttribute("cn").get(0).getAttributeType(); index = ec.getAttributeIndex(attribute); addKeys = new HashSet<byte[]>(); presenceIndexer = new PresenceIndexer(index.getAttributeType()); presenceIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(index.presenceIndex.containsID(null, key, entryID), ConditionResult.FALSE); addKeys = new HashSet<byte[]>(); equalityIndexer = new EqualityIndexer(index.getAttributeType()); equalityIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(index.equalityIndex.containsID(null, key, entryID), ConditionResult.FALSE); addKeys = new HashSet<byte[]>(); substringIndexer = new SubstringIndexer(index.getAttributeType(), index.getConfiguration().getSubstringLength()); substringIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(index.substringIndex.containsID(null, key, entryID), ConditionResult.FALSE); addKeys = new HashSet<byte[]>(); orderingIndexer = new OrderingIndexer(index.getAttributeType()); orderingIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(index.orderingIndex.containsID(null, key, entryID), ConditionResult.FALSE); } finally { ec.sharedLock.unlock(); } } @Test(dependsOnMethods = {"testSearchNotIndexed", "testAdd", "testSearchIndex", "testSearchScope", "testMatchedDN", "testNumSubordinates", "testNumSubordinatesIndexEntryLimitExceeded"}) public void testReplaceEntry() throws Exception { Entry entry; Entry oldEntry; EntryID entryID; AttributeType attribute; AttributeIndex index; HashSet<byte[]> addKeys; DatabaseEntry key; EqualityIndexer equalityIndexer; SubstringIndexer substringIndexer; OrderingIndexer orderingIndexer; oldEntry = entries.get(0); backend.replaceEntry(oldEntry, replaceEntry, null); EntryContainer ec = backend.getRootContainer().getEntryContainer(DN.decode("dc=test,dc=com")); ec.sharedLock.lock(); try { entry = ec.getEntry(DN.decode("uid=user.0,ou=People,dc=test,dc=com")); entryID = ec.getDN2ID().get(null, DN.decode("uid=user.0,ou=People,dc=test,dc=com"), LockMode.DEFAULT); assertNotNull(entry); for (AttributeValue value : entry.getAttribute("cn").get(0)) { assertEquals(value.getValue().toString(), "Testing Test"); } for (AttributeValue value : entry.getAttribute("sn").get(0)) { assertEquals(value.getValue().toString(), "Test"); } for (AttributeValue value : entry.getAttribute("givenname").get(0)) { assertEquals(value.getValue().toString(), "Testing"); } for (AttributeValue value : entry.getAttribute("employeenumber").get(0)) { assertEquals(value.getValue().toString(), "777"); } attribute = entry.getAttribute("cn").get(0).getAttributeType(); index = ec.getAttributeIndex(attribute); addKeys = new HashSet<byte[]>(); orderingIndexer = new OrderingIndexer(index.getAttributeType()); orderingIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(index.orderingIndex.containsID(null, key, entryID), ConditionResult.TRUE); addKeys = new HashSet<byte[]>(); orderingIndexer.indexEntry(oldEntry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(index.orderingIndex.containsID(null, key, entryID), ConditionResult.FALSE); addKeys = new HashSet<byte[]>(); substringIndexer = new SubstringIndexer(index.getAttributeType(), index.getConfiguration().getSubstringLength()); substringIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(index.substringIndex.containsID(null, key, entryID), ConditionResult.TRUE); addKeys = new HashSet<byte[]>(); substringIndexer.indexEntry(oldEntry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(index.substringIndex.containsID(null, key, entryID), ConditionResult.FALSE); addKeys = new HashSet<byte[]>(); equalityIndexer = new EqualityIndexer(index.getAttributeType()); equalityIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(index.equalityIndex.containsID(null, key, entryID), ConditionResult.TRUE); addKeys = new HashSet<byte[]>(); equalityIndexer.indexEntry(oldEntry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(index.equalityIndex.containsID(null, key, entryID), ConditionResult.FALSE); } finally { ec.sharedLock.unlock(); } } @Test(dependsOnMethods = {"testSearchNotIndexed", "testAdd", "testSearchIndex", "testSearchScope", "testMatchedDN", "testNumSubordinates", "testNumSubordinatesIndexEntryLimitExceeded"}) public void testModifyEntry() throws Exception { Entry entry; Entry newEntry; EntryID entryID; AttributeType attribute; AttributeIndex titleIndex; AttributeIndex nameIndex; HashSet<byte[]> addKeys; DatabaseEntry key; PresenceIndexer presenceIndexer; EqualityIndexer equalityIndexer; SubstringIndexer substringIndexer; OrderingIndexer orderingIndexer; EntryContainer ec = backend.getRootContainer().getEntryContainer( DN.decode("dc=test,dc=com")); ec.sharedLock.lock(); try { ArrayList<Modification> modifications = new ArrayList<Modification>(); modifications.add(new Modification(ModificationType.ADD, Attributes .create("title", "debugger"))); AttributeBuilder builder = new AttributeBuilder("title"); builder.setOption("lang-en"); builder.add("debugger2"); modifications.add(new Modification(ModificationType.ADD, builder .toAttribute())); modifications.add(new Modification(ModificationType.DELETE, Attributes.create("cn", "Aaren Atp"))); modifications.add(new Modification(ModificationType.ADD, Attributes .create("cn", "Aaren Rigor"))); modifications.add(new Modification(ModificationType.ADD, Attributes .create("cn", "Aarenister Rigor"))); builder = new AttributeBuilder("givenname"); builder.add("test"); builder.setOption("lang-de"); modifications.add(new Modification(ModificationType.ADD, builder .toAttribute())); builder = new AttributeBuilder("givenname"); builder.add("test2"); builder.setOption("lang-cn"); modifications.add(new Modification(ModificationType.DELETE, builder .toAttribute())); builder = new AttributeBuilder("givenname"); builder.add("newtest3"); builder.setOption("lang-es"); modifications.add(new Modification(ModificationType.REPLACE, builder .toAttribute())); modifications.add(new Modification(ModificationType.REPLACE, Attributes.create("employeenumber", "222"))); newEntry = entries.get(1); newEntry.applyModifications(modifications); entry = ec.getEntry(DN.decode("uid=user.1,ou=People,dc=test,dc=com")); entryID = ec.getDN2ID().get(null, DN.decode("uid=user.1,ou=People,dc=test,dc=com"), LockMode.DEFAULT); assertNotNull(entryID); attribute = DirectoryServer.getAttributeType("title"); titleIndex = ec.getAttributeIndex(attribute); attribute = DirectoryServer.getAttributeType("name"); nameIndex = ec.getAttributeIndex(attribute); // This current entry in the DB shouldn't be in the presence // titleIndex. addKeys = new HashSet<byte[]>(); addKeys.add(AttributeIndex.presenceKey.getData()); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(titleIndex.presenceIndex.containsID(null, key, entryID), ConditionResult.FALSE); // This current entry should be in the presence nameIndex. addKeys = new HashSet<byte[]>(); addKeys.add(AttributeIndex.presenceKey.getData()); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); } assertEquals(nameIndex.presenceIndex.containsID(null, key, entryID), ConditionResult.TRUE); ArrayList<Control> noControls = new ArrayList<Control>(0); InternalClientConnection conn = InternalClientConnection .getRootConnection(); ModifyOperationBasis modifyOp = new ModifyOperationBasis(conn, InternalClientConnection .nextOperationID(), InternalClientConnection.nextMessageID(), noControls, DN .decode("uid=user.1,ou=People,dc=test,dc=com"), modifications); backend.replaceEntry(entry, newEntry, modifyOp); entry = ec.getEntry(DN.decode("uid=user.1,ou=People,dc=test,dc=com")); assertTrue(entry.getAttribute("title").contains( Attributes.create("title", "debugger"))); assertTrue(entry.getAttribute("cn").get(0) .contains( AttributeValues.create(entry.getAttribute("cn").get(0) .getAttributeType(), "Aaren Rigor"))); assertTrue(entry.getAttribute("cn").get(0).contains( AttributeValues.create( entry.getAttribute("cn").get(0).getAttributeType(), "Aarenister Rigor"))); assertFalse(entry.getAttribute("cn").get(0).contains( AttributeValues.create( entry.getAttribute("cn").get(0).getAttributeType(), "Aaren Atp"))); Set<String> options = new LinkedHashSet<String>(); options.add("lang-de"); assertTrue(entry.getAttribute("givenname", options).get(0).contains( AttributeValues.create(entry.getAttribute("givenname", options).get(0) .getAttributeType(), "test"))); options = new LinkedHashSet<String>(); options.add("lang-cn"); assertNull(entry.getAttribute("givenname", options)); options = new LinkedHashSet<String>(); options.add("lang-es"); assertTrue(entry.getAttribute("givenname", options).get(0).contains( AttributeValues.create(entry.getAttribute("givenname", options).get(0) .getAttributeType(), "newtest3"))); options = new LinkedHashSet<String>(); options.add("lang-fr"); assertTrue(entry.getAttribute("givenname", options).get(0).contains( AttributeValues.create(entry.getAttribute("givenname", options).get(0) .getAttributeType(), "test2"))); assertTrue(entry.getAttribute("employeenumber").contains( Attributes.create("employeenumber", "222"))); assertFalse(entry.getAttribute("employeenumber").contains( Attributes.create("employeenumber", "1"))); addKeys = new HashSet<byte[]>(); presenceIndexer = new PresenceIndexer(titleIndex.getAttributeType()); presenceIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); assertEquals(titleIndex.presenceIndex.containsID(null, key, entryID), ConditionResult.TRUE); } addKeys = new HashSet<byte[]>(); presenceIndexer = new PresenceIndexer(nameIndex.getAttributeType()); presenceIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); assertEquals(nameIndex.presenceIndex.containsID(null, key, entryID), ConditionResult.TRUE); } addKeys = new HashSet<byte[]>(); orderingIndexer = new OrderingIndexer(titleIndex.getAttributeType()); orderingIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); assertEquals(titleIndex.orderingIndex.containsID(null, key, entryID), ConditionResult.TRUE); } addKeys = new HashSet<byte[]>(); orderingIndexer = new OrderingIndexer(nameIndex.getAttributeType()); orderingIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); assertEquals(nameIndex.orderingIndex.containsID(null, key, entryID), ConditionResult.TRUE); } addKeys = new HashSet<byte[]>(); equalityIndexer = new EqualityIndexer(titleIndex.getAttributeType()); equalityIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); assertEquals(titleIndex.equalityIndex.containsID(null, key, entryID), ConditionResult.TRUE); } addKeys = new HashSet<byte[]>(); equalityIndexer = new EqualityIndexer(nameIndex.getAttributeType()); equalityIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); assertEquals(nameIndex.equalityIndex.containsID(null, key, entryID), ConditionResult.TRUE); } addKeys = new HashSet<byte[]>(); substringIndexer = new SubstringIndexer(titleIndex.getAttributeType(), titleIndex.getConfiguration().getSubstringLength()); substringIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); assertEquals(titleIndex.substringIndex.containsID(null, key, entryID), ConditionResult.TRUE); } addKeys = new HashSet<byte[]>(); substringIndexer = new SubstringIndexer(nameIndex.getAttributeType(), nameIndex.getConfiguration().getSubstringLength()); substringIndexer.indexEntry(entry, addKeys); key = new DatabaseEntry(); for (byte[] keyBytes : addKeys) { key.setData(keyBytes); assertEquals(nameIndex.substringIndex.containsID(null, key, entryID), ConditionResult.TRUE); } } finally { ec.sharedLock.unlock(); } } @Test(dependsOnMethods = {"testAdd", "testSearchIndex", "testSearchScope", "testMatchedDN"}) public void testModifyDN() throws Exception { EntryContainer ec = backend.getRootContainer().getEntryContainer(DN.decode("dc=test,dc=com")); ec.sharedLock.lock(); try { Entry entry = ec.getEntry(DN.decode("uid=user.2,ou=People,dc=test,dc=com")); entry.setDN(DN.decode("cn=Abbey Abbie,ou=People,dc=test,dc=com")); backend.renameEntry(DN.decode("uid=user.2,ou=People,dc=test,dc=com"), entry, null); assertNotNull(backend.getEntry(DN.decode("cn=Abbey Abbie,ou=People,dc=test,dc=com"))); assertNotNull(ec.getDN2ID().get(null, DN.decode("cn=Abbey Abbie,ou=People,dc=test,dc=com"), LockMode.DEFAULT)); assertNull(backend.getEntry(DN.decode("uid=user.2,ou=People,dc=test,dc=com"))); assertNull(ec.getDN2ID().get(null, DN.decode("uid=user.2,ou=People,dc=test,dc=com"), LockMode.DEFAULT)); } finally { ec.sharedLock.unlock(); } } @Test(dependsOnMethods = {"testSearchNotIndexed", "testAdd", "testSearchIndex", "testSearchScope", "testModifyEntry", "testModifyDN", "testReplaceEntry", "testDeleteEntry", "testMatchedDN", "testNumSubordinates", "testNumSubordinatesIndexEntryLimitExceeded"}) public void testModifyDNNewSuperior() throws Exception { //Add the new superior entry we want to move to. Test to see if the child ID //always above parent invarient is preseved. backend.addEntry(newTop, null); EntryContainer ec = backend.getRootContainer().getEntryContainer(DN.decode("dc=test,dc=com")); ec.sharedLock.lock(); try { EntryID newSuperiorID = ec.getDN2ID().get(null, DN.decode("ou=JEB Testers,dc=test,dc=com"), LockMode.DEFAULT); EntryID oldID = ec.getDN2ID().get(null, DN.decode("ou=People,dc=test,dc=com"), LockMode.DEFAULT); assertTrue(newSuperiorID.compareTo(oldID) > 0); ArrayList<Control> noControls = new ArrayList<Control>(0); InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperationBasis modifyDN = new ModifyDNOperationBasis(conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), noControls, DN.decode("ou=People,dc=test,dc=com"), RDN.decode("ou=Good People"), false, DN.decode("ou=JEB Testers,dc=test,dc=com")); modifyDN.run(); assertNotNull(backend.getEntry(DN.decode("ou=Good People,ou=JEB Testers,dc=test,dc=com"))); EntryID newID = ec.getDN2ID().get(null, DN.decode("ou=Good People,ou=JEB Testers,dc=test,dc=com"), LockMode.DEFAULT); assertNotNull(newID); assertTrue(newID.compareTo(newSuperiorID) > 0); DN subDN = DN.decode("uid=user.0,ou=Good People,ou=JEB Testers,dc=test,dc=com"); Entry subEntry = backend.getEntry(subDN); assertNotNull(subEntry); assertEquals(subDN, subEntry.getDN()); EntryID newSubordinateID = ec.getDN2ID().get(null, subDN, LockMode.DEFAULT); assertTrue(newSubordinateID.compareTo(newID) > 0); assertNull(backend.getEntry(DN.decode("ou=People,dc=test,dc=com"))); assertNull(ec.getDN2ID().get(null, DN.decode("ou=People,dc=test,dc=com"), LockMode.DEFAULT)); } finally { ec.sharedLock.unlock(); } } @Test(dependsOnMethods = {"testModifyDN", "testSearchScope", "testSearchIndex", "testReplaceEntry", "testModifyEntry", "testModifyDN", "testDeleteSubtree", "testDeleteEntry", "testAddNoParent", "testAdd", "testSearchNotIndexed", "testModifyDNNewSuperior", "testApplyIndexConfig", "testMatchedDN"}) public void testApplyConfig() throws Exception { Entry configEntry = TestCaseUtils.makeEntry( "dn: ds-cfg-backend-id=indexRoot,cn=Backends,cn=config", "objectClass: top", "objectClass: ds-cfg-backend", "objectClass: ds-cfg-local-db-backend", "ds-cfg-base-dn: dc=test,dc=com", "ds-cfg-base-dn: dc=newsuffix,dc=com", "ds-cfg-enabled: true", "ds-cfg-writability-mode: enabled", "ds-cfg-java-class: org.opends.server.backends.jeb.BackendImpl", "ds-cfg-backend-id: indexRoot", "ds-cfg-db-directory:: " + Base64.encode(homeDirName.getBytes()), "ds-cfg-import-temp-directory: import-tmp"); LocalDBBackendCfg cfg = AdminTestCaseUtils.getConfiguration( LocalDBBackendCfgDefn.getInstance(), configEntry); backend.applyConfigurationChange(cfg); RootContainer rootContainer = backend.getRootContainer(); assertNull(rootContainer.getEntryContainer(DN.decode("dc=test1,dc=com"))); assertNotNull(rootContainer.getEntryContainer(DN.decode("dc=newsuffix,dc=com"))); } @Test(dependsOnMethods = {"testModifyDN", "testSearchScope", "testSearchIndex", "testReplaceEntry", "testModifyEntry", "testModifyDN", "testDeleteSubtree", "testDeleteEntry", "testAddNoParent", "testAdd", "testSearchNotIndexed", "testModifyDNNewSuperior", "testMatchedDN"}) public void testApplyIndexConfig() throws Exception { int resultCode = TestCaseUtils.applyModifications(true, "dn: ds-cfg-attribute=givenName,cn=Index," + "ds-cfg-backend-id=indexRoot,cn=Backends,cn=config", "changetype: modify", "replace: ds-cfg-index-type", "ds-cfg-index-type: approximate"); assertEquals(resultCode, 0); RootContainer rootContainer = backend.getRootContainer(); EntryContainer ec = rootContainer.getEntryContainer(DN.decode("dc=test,dc=com")); AttributeIndex index = ec.getAttributeIndex(DirectoryServer.getAttributeType("givenname")); assertNull(index.equalityIndex); assertNull(index.presenceIndex); assertNull(index.substringIndex); assertNull(index.orderingIndex); assertNotNull(index.approximateIndex); ArrayList<DatabaseContainer> databases = new ArrayList<DatabaseContainer>(); ec.listDatabases(databases); boolean eqfound = false; boolean prfound = false; boolean subfound = false; boolean orfound = false; boolean apfound = false; for(DatabaseContainer dc : databases) { if(dc.getName().toLowerCase().contains("givenname.approximate")) { apfound = true; } if(dc.getName().toLowerCase().contains("givenname.presence")) { prfound = true; } if(dc.getName().toLowerCase().contains("givenname.substring")) { subfound = true; } if(dc.getName().toLowerCase().contains("givenname.ordering")) { orfound = true; } if(dc.getName().toLowerCase().contains("givenname.equality")) { eqfound = true; } } assertFalse(eqfound); assertFalse(prfound); assertFalse(subfound); assertFalse(orfound); assertTrue(apfound); InternalClientConnection conn = InternalClientConnection.getRootConnection(); LinkedHashSet<String> attribs = new LinkedHashSet<String>(); attribs.add(ATTR_DEBUG_SEARCH_INDEX); InternalSearchOperation search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.SUBORDINATE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, LDAPFilter.decode("(givenName~=Aaccf)"). toSearchFilter(), attribs); LinkedList<SearchResultEntry> result = search.getSearchEntries(); //No indexes should be used. String debugString = result.get(0).getAttribute("debugsearchindex").get(0).toString(); assertTrue(debugString.contains("NOT-INDEXED")); resultCode = TestCaseUtils.applyModifications(true, "dn: ds-cfg-attribute=givenName,cn=Index," + "ds-cfg-backend-id=indexRoot,cn=Backends,cn=config", "changetype: modify", "replace: ds-cfg-index-type", "ds-cfg-index-type: equality", "ds-cfg-index-type: presence", "ds-cfg-index-type: ordering", "ds-cfg-index-type: substring"); assertEquals(resultCode, 0); assertNotNull(index.equalityIndex); assertNotNull(index.presenceIndex); assertNotNull(index.substringIndex); assertNotNull(index.orderingIndex); assertNull(index.approximateIndex); databases = new ArrayList<DatabaseContainer>(); ec.listDatabases(databases); eqfound = false; prfound = false; subfound = false; orfound = false; apfound = false; for(DatabaseContainer dc : databases) { if(dc.getName().toLowerCase().contains("givenname.approximate")) { apfound = true; } if(dc.getName().toLowerCase().contains("givenname.presence")) { prfound = true; } if(dc.getName().toLowerCase().contains("givenname.substring")) { subfound = true; } if(dc.getName().toLowerCase().contains("givenname.ordering")) { orfound = true; } if(dc.getName().toLowerCase().contains("givenname.equality")) { eqfound = true; } } assertTrue(eqfound); assertTrue(prfound); assertTrue(subfound); assertTrue(orfound); assertFalse(apfound); // Delete the entries attribute index. resultCode = TestCaseUtils.applyModifications(true, "dn: ds-cfg-attribute=givenName,cn=Index," + "ds-cfg-backend-id=indexRoot,cn=Backends,cn=config", "changetype: delete"); assertEquals(resultCode, 0); assertNull(ec.getAttributeIndex( DirectoryServer.getAttributeType("givenname"))); databases = new ArrayList<DatabaseContainer>(); ec.listDatabases(databases); for(DatabaseContainer dc : databases) { assertFalse(dc.getName().toLowerCase().contains("givenname")); } // Add it back resultCode = TestCaseUtils.applyModifications(true, "dn: ds-cfg-attribute=givenName,cn=Index," + "ds-cfg-backend-id=indexRoot,cn=Backends,cn=config", "changetype: add", "objectClass: top", "objectClass: ds-cfg-local-db-index", "ds-cfg-attribute: givenName", "ds-cfg-index-type: equality", "ds-cfg-index-type: presence", "ds-cfg-index-type: ordering", "ds-cfg-index-type: substring"); assertEquals(resultCode, 0); assertNotNull(ec.getAttributeIndex( DirectoryServer.getAttributeType("givenname"))); databases = new ArrayList<DatabaseContainer>(); ec.listDatabases(databases); eqfound = false; prfound = false; subfound = false; orfound = false; apfound = false; for(DatabaseContainer dc : databases) { if(dc.getName().toLowerCase().contains("givenname.approximate")) { apfound = true; } if(dc.getName().toLowerCase().contains("givenname.presence")) { prfound = true; } if(dc.getName().toLowerCase().contains("givenname.substring")) { subfound = true; } if(dc.getName().toLowerCase().contains("givenname.ordering")) { orfound = true; } if(dc.getName().toLowerCase().contains("givenname.equality")) { eqfound = true; } } assertTrue(eqfound); assertTrue(prfound); assertTrue(subfound); assertTrue(orfound); assertFalse(apfound); // Make sure changing the index entry limit on an index where the limit // is already exceeded causes warnings. resultCode = TestCaseUtils.applyModifications(true, "dn: ds-cfg-attribute=mail,cn=Index," + "ds-cfg-backend-id=indexRoot,cn=Backends,cn=config", "changetype: modify", "replace: ds-cfg-index-entry-limit", "ds-cfg-index-entry-limit: 30"); assertEquals(resultCode, 0); // Make sure removing a index entry limit for an index makes it use the // backend wide setting. resultCode = TestCaseUtils.applyModifications(true, "dn: ds-cfg-attribute=mail,cn=Index," + "ds-cfg-backend-id=indexRoot,cn=Backends,cn=config", "changetype: modify", "delete: ds-cfg-index-entry-limit"); assertEquals(resultCode, 0); } @Test(dependsOnMethods = {"testDeleteEntry", "testSearchScope", "testSearchIndex", "testMatchedDN"}) public void testSearchNotIndexed() throws Exception { //Add 2 more entries to overflow the index entry limit. for (Entry entry : additionalEntries) { backend.addEntry(entry, null); assertNotNull(backend.getEntry(entry.getDN())); } InternalClientConnection conn = InternalClientConnection.getRootConnection(); LinkedHashSet<String> attribs = new LinkedHashSet<String>(); attribs.add(ATTR_DEBUG_SEARCH_INDEX); String debugString; InternalSearchOperation search = conn.processSearch(DN.decode("dc=test,dc=com"), SearchScope.SUBORDINATE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, LDAPFilter.decode("(carLicense=377*)").toSearchFilter(), attribs); LinkedList<SearchResultEntry> result = search.getSearchEntries(); //No indexes should be used. debugString = result.get(0).getAttribute("debugsearchindex").get(0).toString(); assertTrue(debugString.contains("NOT-INDEXED")); } @Test(dependsOnMethods = "testSearchNotIndexed") public void testNumSubordinatesIndexEntryLimitExceeded() throws Exception { DN dn = DN.decode("dc=test,dc=com"); assertEquals(backend.numSubordinates(dn, false), 1); assertEquals(backend.numSubordinates(dn, true), 14); // 1 entry was deleted and 2 added for a total of 13 dn = DN.decode("ou=People,dc=test,dc=com"); assertEquals(backend.numSubordinates(dn, false), 13); assertEquals(backend.numSubordinates(dn, true), 13); dn = DN.decode("dc=com"); assertEquals(backend.numSubordinates(dn, false), -1); assertEquals(backend.numSubordinates(dn, true), -1); dn = DN.decode("dc=test1,dc=com"); assertEquals(backend.numSubordinates(dn, false), 2); assertEquals(backend.numSubordinates(dn, true), 2); dn = DN.decode("uid=user.10,ou=People,dc=test,dc=com"); assertEquals(backend.numSubordinates(dn, false), 0); assertEquals(backend.numSubordinates(dn, true), 0); dn = DN.decode("uid=does not exist,ou=People,dc=test,dc=com"); assertEquals(backend.numSubordinates(dn, false), -1); assertEquals(backend.numSubordinates(dn, true), -1); } /** * Provides a set of DNs for the matched DN test case. * * @return set of DNs * @throws Exception when DN.decode fails */ @DataProvider(name = "MatchedDNs") public Object[][] initMatchedDNs() throws Exception { ResultCode success = ResultCode.SUCCESS; ResultCode noSuchObject = ResultCode.NO_SUCH_OBJECT; DN testComDN = null; DN peopleTestComDN = null; DN dummyTestComDN = null; DN dummyPeopleTestComDN = null; try { testComDN = DN.decode( "dc=test,dc=com"); dummyTestComDN = DN.decode( "cn=dummy,dc=test,dc=com"); peopleTestComDN = DN.decode( "ou=people,dc=test,dc=com"); dummyPeopleTestComDN = DN.decode("cn=dummy,ou=people,dc=test,dc=com"); } catch (DirectoryException de) { throw de; } // Sets of DNs Object[][] myData = { {testComDN, null, success}, {peopleTestComDN, null, success}, {dummyTestComDN, testComDN, noSuchObject}, {dummyPeopleTestComDN, peopleTestComDN, noSuchObject}, }; return myData; } /** * Executes an internal search operation and check the result code and * matched DN field. * * @param searchBaseDN the search base DN to use for the current test * @param expectedResultCode the expected LDAP result code * @param expectedMatchedDN the expected matched DN, may be <code>null</code> */ @Test(dataProvider = "MatchedDNs", dependsOnMethods = "testAdd") public void testMatchedDN( DN searchBaseDN, DN expectedMatchedDN, ResultCode expectedResultCode ) throws Exception { InternalClientConnection conn = InternalClientConnection.getRootConnection(); // Filter for the search SearchFilter filter = LDAPFilter.decode("(objectClass=*)").toSearchFilter(); // Test is performed with each and every scope for (SearchScope scope: SearchScope.values()) { InternalSearchOperation searchOperation = conn.processSearch(searchBaseDN, scope, filter); assertEquals(searchOperation.getResultCode(), expectedResultCode); assertEquals(searchOperation.getMatchedDN(), expectedMatchedDN); } } }