| New file |
| | |
| | | /* |
| | | * 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 2015 ForgeRock AS |
| | | */ |
| | | |
| | | package org.opends.server.backends.pluggable; |
| | | |
| | | import static org.forgerock.opendj.ldap.ModificationType.ADD; |
| | | import static org.opends.server.protocols.internal.InternalClientConnection.getRootConnection; |
| | | import static org.opends.server.protocols.internal.Requests.newSearchRequest; |
| | | import static org.opends.server.types.Attributes.create; |
| | | import static org.testng.Assert.assertEquals; |
| | | import static org.testng.Assert.assertFalse; |
| | | import static org.testng.Assert.assertNotNull; |
| | | import static org.testng.Assert.assertNull; |
| | | import static org.testng.Assert.assertTrue; |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Random; |
| | | |
| | | import org.assertj.core.api.Assertions; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ConditionResult; |
| | | import org.forgerock.opendj.ldap.SearchScope; |
| | | import org.opends.server.DirectoryServerTestCase; |
| | | import org.opends.server.TestCaseUtils; |
| | | 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.internal.SearchRequest; |
| | | import org.opends.server.tools.makeldif.TemplateFile; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.BackupConfig; |
| | | import org.opends.server.types.BackupDirectory; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.IndexType; |
| | | import org.opends.server.types.LDIFExportConfig; |
| | | import org.opends.server.types.LDIFImportConfig; |
| | | import org.opends.server.types.Modification; |
| | | import org.opends.server.types.RestoreConfig; |
| | | import org.opends.server.types.SearchResultEntry; |
| | | import org.opends.server.workflowelement.localbackend.LocalBackendSearchOperation; |
| | | import org.testng.Reporter; |
| | | import org.testng.annotations.AfterClass; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.Test; |
| | | |
| | | /** |
| | | * BackendImpl Tester. |
| | | */ |
| | | @SuppressWarnings("javadoc") |
| | | @Test(groups = { "precommit", "pluggablebackend" }, sequential = true) |
| | | public abstract class PluggableBackendImplTestCase extends DirectoryServerTestCase |
| | | { |
| | | protected BackendImpl backend; |
| | | |
| | | protected List<Entry> topEntries; |
| | | protected List<Entry> entries; |
| | | protected List<Entry> workEntries; |
| | | protected DN testBaseDN; |
| | | protected DN dnToMod; |
| | | protected DN dnToDel; |
| | | protected DN searchDN; |
| | | protected DN badEntryDN; |
| | | protected String[] ldifTemplate; |
| | | protected int ldifNumberOfEntries; |
| | | protected String backupID; |
| | | protected String[] backendIndexes = { "sn" }; |
| | | protected String[] backendVlvIndexes = {}; |
| | | |
| | | private AttributeType modifyAttribute; |
| | | private final ByteString modifyValue = ByteString.valueOf("foo"); |
| | | private String backupPath; |
| | | private BackupDirectory backupDirectory; |
| | | |
| | | /** |
| | | * Configures a backend for the specified backend |
| | | * |
| | | * @param homeDirName |
| | | * Directory where database file live |
| | | * @param testBaseDN |
| | | * Root DN for the DIT |
| | | * @return a backend object. |
| | | */ |
| | | protected abstract BackendImpl createBackend() throws Exception; |
| | | |
| | | @BeforeClass |
| | | public void setUp() throws Exception |
| | | { |
| | | // Need the schema to be available, so make sure the server is started. |
| | | TestCaseUtils.startServer(); |
| | | |
| | | testBaseDN = DN.valueOf("dc=test,dc=com"); |
| | | backend = createBackend(); |
| | | backend.initializeBackend(); |
| | | |
| | | topEntries = TestCaseUtils.makeEntries( |
| | | "dn: " + testBaseDN, |
| | | "objectclass: top", |
| | | "objectclass: domain", |
| | | "", |
| | | "dn: ou=People," + testBaseDN, |
| | | "objectclass: top", |
| | | "objectclass: organizationalUnit", |
| | | "ou: People"); |
| | | entries = TestCaseUtils.makeEntries( |
| | | "dn: uid=user.0,ou=People," + testBaseDN, |
| | | "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," + testBaseDN, |
| | | "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," + testBaseDN, |
| | | "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," + testBaseDN, |
| | | "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," + testBaseDN, |
| | | "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," + testBaseDN, |
| | | "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," + testBaseDN, |
| | | "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," + testBaseDN, |
| | | "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," + testBaseDN, |
| | | "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," + testBaseDN, |
| | | "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," + testBaseDN, |
| | | "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," + testBaseDN, |
| | | "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."); |
| | | |
| | | workEntries = TestCaseUtils.makeEntries( |
| | | "dn: uid=user.11,ou=People," + testBaseDN, |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "givenName: Annalee", |
| | | "sn: Avard", |
| | | "cn: Annalee Avard", |
| | | "initials: ANA", |
| | | "employeeNumber: 11", |
| | | "uid: user.11", |
| | | "mail: user.11@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.12,ou=People," + testBaseDN, |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "givenName: Andaree", |
| | | "sn: Asawa", |
| | | "cn: Andaree Asawa", |
| | | "initials: AEA", |
| | | "employeeNumber: 12", |
| | | "uid: user.12", |
| | | "mail: user.12@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."); |
| | | |
| | | dnToMod = workEntries.get(0).getName(); |
| | | dnToDel = workEntries.get(1).getName(); |
| | | searchDN = entries.get(8).getName(); |
| | | badEntryDN = testBaseDN.child(DN.valueOf("ou=bogus")).child(DN.valueOf("ou=dummy")); |
| | | backupID = "backupID1"; |
| | | |
| | | ldifNumberOfEntries = 20; |
| | | ldifTemplate = new String [] { |
| | | "define suffix=" + testBaseDN, |
| | | "define maildomain=" + testBaseDN, |
| | | "define numusers = " + ldifNumberOfEntries, |
| | | "", |
| | | "branch: [suffix]", |
| | | "objectClass: domain", |
| | | "", |
| | | "branch: ou=People,[suffix]", |
| | | "objectClass: organizationalUnit", |
| | | "subordinateTemplate: person:[numusers]", |
| | | "", |
| | | "template: person", |
| | | "rdnAttr: uid", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "givenName: ABOVE LIMIT", |
| | | "sn: <last>", |
| | | "cn: {givenName} {sn}", |
| | | "initials: {givenName:1}<random:chars:ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>{sn:1}", |
| | | "employeeNumber: <sequential:0>", |
| | | "uid: user.{employeeNumber}", |
| | | "mail: {uid}@[maildomain]", |
| | | "userPassword: password", |
| | | "telephoneNumber: <random:telephone>", |
| | | "homePhone: <random:telephone>", |
| | | "pager: <random:telephone>", |
| | | "mobile: <random:telephone>", |
| | | "street: <random:numeric:5> <file:streets> Street", |
| | | "l: <file:cities>", |
| | | "st: <file:states>", |
| | | "postalCode: <random:numeric:5>", |
| | | "postalAddress: {cn}${street}${l}, {st} {postalCode}", |
| | | "description: This is the description for {cn}.", |
| | | ""}; |
| | | // Add suffix and barnch entries |
| | | ldifNumberOfEntries += 2; |
| | | } |
| | | |
| | | @AfterClass |
| | | public void cleanUp() throws Exception |
| | | { |
| | | try |
| | | { |
| | | backend.removeBackup(backupDirectory, backupID); |
| | | } |
| | | catch (DirectoryException ignore) |
| | | { |
| | | /* |
| | | * Due to test sequencing (Import, backup, restore, export) in case of intermediate failure |
| | | * Backup may or may not be present. -> ignore. |
| | | */ |
| | | Reporter.log(ignore.getMessage(), true); |
| | | } |
| | | finally |
| | | { |
| | | backend.finalizeBackend(); |
| | | backend = null; |
| | | } |
| | | } |
| | | |
| | | public void testAdd() throws Exception |
| | | { |
| | | addEntriesToBackend(topEntries); |
| | | addEntriesToBackend(entries); |
| | | addEntriesToBackend(workEntries); |
| | | } |
| | | |
| | | /** |
| | | * Helper for add entries in a backend. |
| | | * @throws Exception |
| | | */ |
| | | private void addEntriesToBackend(List<Entry> entries) throws Exception |
| | | { |
| | | for (Entry newEntry : entries) |
| | | { |
| | | backend.addEntry(newEntry, null); |
| | | } |
| | | } |
| | | |
| | | @Test(expectedExceptions = DirectoryException.class) |
| | | public void testAddNoParent() throws Exception |
| | | { |
| | | Entry newEntry = TestCaseUtils.makeEntry("dn: " + badEntryDN, "objectclass: ou", ""); |
| | | backend.addEntry(newEntry, null); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = "testAdd") |
| | | public void testUtilityAPIs() |
| | | { |
| | | assertEquals(backend.getEntryCount(), getTotalNumberOfLDIFEntries()); |
| | | assertFalse(backend.isIndexed(modifyAttribute, IndexType.EQUALITY)); |
| | | assertTrue(backend.isIndexed(DirectoryServer.getAttributeType(backendIndexes[0]), IndexType.EQUALITY)); |
| | | } |
| | | |
| | | private int getTotalNumberOfLDIFEntries() |
| | | { |
| | | return topEntries.size() + entries.size() + workEntries.size(); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = "testAdd") |
| | | public void testHasSubordinates() throws Exception |
| | | { |
| | | assertEquals(backend.hasSubordinates(testBaseDN), ConditionResult.TRUE, |
| | | "Base DN should have subordinates."); |
| | | |
| | | // Testing ConditionResult.UNDEFINED needs either no entry container or a big DIT... |
| | | assertEquals(backend.hasSubordinates(DN.valueOf("dc=a")), ConditionResult.UNDEFINED, |
| | | "Subordinates query on unknown baseDN should return UNDEFINED."); |
| | | |
| | | assertEquals(backend.numSubordinates(testBaseDN, false), 1); |
| | | assertEquals(backend.numSubordinates(testBaseDN, true), getTotalNumberOfLDIFEntries() - 1, "Wrong DIT count."); |
| | | assertEquals(backend.hasSubordinates(searchDN), ConditionResult.FALSE, |
| | | "Leaf entry should not have any subordinates."); |
| | | } |
| | | |
| | | private List<SearchResultEntry> runSearch(SearchRequest request, boolean useInternalConnection) throws Exception |
| | | { |
| | | InternalClientConnection conn = getRootConnection(); |
| | | |
| | | if (useInternalConnection) |
| | | { |
| | | InternalSearchOperation search = conn.processSearch(request); |
| | | return search.getSearchEntries(); |
| | | } |
| | | else |
| | | { |
| | | InternalSearchOperation search = new InternalSearchOperation(conn, -1, -1, request); |
| | | backend.search(new LocalBackendSearchOperation(search)); |
| | | return search.getSearchEntries(); |
| | | } |
| | | } |
| | | |
| | | @Test(dependsOnMethods = { "testAdd", "testModifyEntry", "testRenameEntry", "testDeleteAlreadyDeletedEntry" }) |
| | | public void testBaseSearch() throws Exception |
| | | { |
| | | baseSearch(false); |
| | | baseSearch(true); |
| | | } |
| | | |
| | | private void baseSearch(boolean useInternalConnection) throws Exception |
| | | { |
| | | SearchRequest request = newSearchRequest(testBaseDN, SearchScope.BASE_OBJECT, "objectclass=*"); |
| | | List<SearchResultEntry> result = runSearch(request, useInternalConnection); |
| | | |
| | | assertEquals(result.size(), 1, "Base Search should return only one Entry"); |
| | | assertEquals(result.get(0).getName(), testBaseDN, "Base Search on the suffix should return the suffix itself"); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = { "testAdd", "testModifyEntry", "testRenameEntry", "testDeleteAlreadyDeletedEntry" }) |
| | | public void testOneLevelSearch() throws Exception |
| | | { |
| | | oneLevelSearch(false); |
| | | oneLevelSearch(true); |
| | | } |
| | | |
| | | private void oneLevelSearch(boolean useInternalConnection) throws Exception |
| | | { |
| | | SearchRequest request = newSearchRequest(testBaseDN, SearchScope.SINGLE_LEVEL, "objectclass=*"); |
| | | List<SearchResultEntry> result = runSearch(request, useInternalConnection); |
| | | |
| | | assertEquals(result.size(), 1, "One Level search should return a single child entry"); |
| | | SearchResultEntry resEntry = result.get(0); |
| | | assertEquals(topEntries.get(1).getName(), resEntry.getName(), |
| | | "One Level search should return the expected child"); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = { "testAdd", "testModifyEntry", "testRenameEntry", "testDeleteAlreadyDeletedEntry" }) |
| | | public void testSubTreeSearch() throws Exception |
| | | { |
| | | subTreeSearch(false); |
| | | subTreeSearch(true); |
| | | } |
| | | |
| | | private void subTreeSearch(boolean useInternalConnection) throws Exception |
| | | { |
| | | SearchRequest request = newSearchRequest(testBaseDN, SearchScope.WHOLE_SUBTREE, "objectclass=*"); |
| | | List<SearchResultEntry> result = runSearch(request, useInternalConnection); |
| | | |
| | | // Sum of all entry sets minus a delete |
| | | assertEquals(result.size(), getTotalNumberOfLDIFEntries() - 1, |
| | | "Subtree search should return a correct number of entries"); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = { "testAdd", "testModifyEntry", "testRenameEntry", "testDeleteAlreadyDeletedEntry" }) |
| | | public void testUserEntrySearch() throws Exception |
| | | { |
| | | userEntrySearch(false); |
| | | userEntrySearch(true); |
| | | } |
| | | |
| | | private void userEntrySearch(boolean useInternalConnection) throws Exception |
| | | { |
| | | SearchRequest request = newSearchRequest(searchDN, SearchScope.BASE_OBJECT, "objectclass=*"); |
| | | List<SearchResultEntry> result = runSearch(request, useInternalConnection); |
| | | |
| | | assertEquals(result.size(), 1, "User entry search should return a single child entry"); |
| | | assertEquals(searchDN, result.get(0).getName(), "User entry search should return the expected entry"); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = { "testAdd", "testModifyEntry", "testRenameEntry", "testDeleteAlreadyDeletedEntry" }) |
| | | public void testGetEntry() throws Exception |
| | | { |
| | | Assertions.assertThat(getDbEntries(entries)).isEqualTo(entries); |
| | | } |
| | | |
| | | private List<Entry> getDbEntries(List<Entry> entries) throws DirectoryException |
| | | { |
| | | List<Entry> result = new ArrayList<Entry>(entries.size()); |
| | | for (Entry currentEntry : entries) |
| | | { |
| | | Entry dbEntry = backend.getEntry(currentEntry.getName()); |
| | | result.add(filterOperationalAttributes(dbEntry)); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private Entry filterOperationalAttributes(Entry e) |
| | | { |
| | | return new Entry(e.getName(), e.getObjectClasses(), e.getUserAttributes(), null); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = { "testAdd", "testModifyEntry" }) |
| | | public void testRenameEntry() throws Exception |
| | | { |
| | | // Move the entire subtree to another name and move it back. |
| | | DN prevDN = DN.valueOf("ou=People," + testBaseDN); |
| | | DN newDN = DN.valueOf("ou=users," + testBaseDN); |
| | | Entry renameEntry = backend.getEntry(prevDN); |
| | | |
| | | renameEntry.setDN(newDN); |
| | | backend.renameEntry(prevDN, renameEntry, null); |
| | | Entry dbEntry = backend.getEntry(newDN); |
| | | assertEquals(dbEntry.getName(), newDN, "Renamed entry is missing."); |
| | | |
| | | renameEntry.setDN(prevDN); |
| | | backend.renameEntry(newDN, renameEntry, null); |
| | | dbEntry = backend.getEntry(prevDN); |
| | | assertEquals(dbEntry.getName(), prevDN, "Original entry has not been renamed"); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = "testAdd") |
| | | public void testModifyEntry() throws Exception |
| | | { |
| | | Entry oldEntry = workEntries.get(0); |
| | | Entry newEntry = oldEntry.duplicate(false); |
| | | |
| | | modifyAttribute = DirectoryServer.getAttributeType("jpegphoto"); |
| | | newEntry.applyModifications(Arrays.asList(new Modification(ADD, create(modifyAttribute, modifyValue)))); |
| | | |
| | | backend.replaceEntry(oldEntry, newEntry, null); |
| | | assertTrue(backend.getEntry(oldEntry.getName()).hasValue(modifyAttribute, null, modifyValue)); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = { "testAdd", "testRenameEntry", "testHasSubordinates" }) |
| | | public void testDeleteEntry() throws Exception |
| | | { |
| | | deleteEntry(dnToDel); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = "testDeleteEntry", expectedExceptions = DirectoryException.class) |
| | | public void testDeleteAlreadyDeletedEntry() throws Exception |
| | | { |
| | | deleteEntry(dnToDel); |
| | | } |
| | | |
| | | private void deleteEntry(DN dn) throws Exception |
| | | { |
| | | backend.deleteEntry(dn, null); |
| | | assertNull(backend.getEntry(workEntries.get(1).getName())); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = { "testBaseSearch", "testOneLevelSearch", "testSubTreeSearch", "testUserEntrySearch" }) |
| | | public void testImportLDIF() throws Exception |
| | | { |
| | | assertTrue(backend.supportsLDIFImport(), "Import not supported"); |
| | | |
| | | // Import wants the backend to be configured but not initialized. Finalizing resets the status. |
| | | backend.finalizeBackend(); |
| | | |
| | | assertNotNull(ldifTemplate, "Import requires an LDIF template"); |
| | | |
| | | String makeLDIFPath = |
| | | System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT) + File.separator + "resource" + File.separator |
| | | + "MakeLDIF"; |
| | | TemplateFile templateFile = new TemplateFile(makeLDIFPath, new Random()); |
| | | templateFile.parse(ldifTemplate, null); |
| | | |
| | | ByteArrayOutputStream rejectedEntries = new ByteArrayOutputStream(); |
| | | |
| | | LDIFImportConfig importConf = new LDIFImportConfig(templateFile); |
| | | importConf.setInvokeImportPlugins(true); |
| | | importConf.setClearBackend(true); |
| | | importConf.writeRejectedEntries(rejectedEntries); |
| | | try { |
| | | backend.importLDIF(importConf); |
| | | } |
| | | finally { |
| | | importConf.close(); |
| | | } |
| | | assertEquals(rejectedEntries.size(), 0, "No entries should be rejected"); |
| | | |
| | | backend.initializeBackend(); |
| | | assertEquals(backend.getEntryCount(), ldifNumberOfEntries, "Not enough entries in DIT."); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = {"testImportLDIF"}) |
| | | public void testPreloadEntryCache() |
| | | { |
| | | // There is no backend.isPreloadSupported(), so try and if it fails, just let it go. |
| | | try |
| | | { |
| | | backend.preloadEntryCache(); |
| | | } |
| | | catch (UnsupportedOperationException uoe) |
| | | { |
| | | Reporter.log("Skipping unsupported Cache Preload", true); |
| | | } |
| | | } |
| | | |
| | | @Test(dependsOnMethods = "testPreloadEntryCache") |
| | | public void testBackup() throws Exception |
| | | { |
| | | assertEquals(backend.supportsBackup(), true, "Skip Backup"); |
| | | assertNotNull(backupID, "Need to setup a backupID"); |
| | | |
| | | backupPath = TestCaseUtils.createTemporaryDirectory("backup").getAbsolutePath(); |
| | | backupDirectory = new BackupDirectory(backupPath, testBaseDN); |
| | | BackupConfig backupConf = new BackupConfig(backupDirectory, backupID, false); |
| | | backupConf.setFilesToBackupFilter(backend.getRootContainer().getStorage().getFilesToBackupFilter()); |
| | | |
| | | backend.createBackup(backupConf); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = "testBackup") |
| | | public void testRestore() throws Exception |
| | | { |
| | | assertTrue(backend.supportsRestore(), "Skip Restore"); |
| | | |
| | | backend.restoreBackup(new RestoreConfig(backupDirectory, backupID, true)); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = "testRestore") |
| | | public void testExportLDIF() throws Exception |
| | | { |
| | | assertTrue(backend.supportsLDIFExport(), "Export not supported"); |
| | | |
| | | ByteArrayOutputStream ldifData = new ByteArrayOutputStream(); |
| | | LDIFExportConfig exportConfig = new LDIFExportConfig(ldifData); |
| | | exportConfig.setIncludeOperationalAttributes(true); |
| | | exportConfig.setIncludeVirtualAttributes(true); |
| | | try |
| | | { |
| | | backend.exportLDIF(exportConfig); |
| | | } |
| | | finally |
| | | { |
| | | exportConfig.close(); |
| | | } |
| | | |
| | | String ldifString = ldifData.toString(); |
| | | assertEquals(ldifString.contains(testBaseDN.toString()), true, "Export without rootDN"); |
| | | assertEquals(ldifString.contains(searchDN.toString()), true, "Export without rootDN"); |
| | | } |
| | | } |