From e7d1a63f1b251ee4139e50877d33d308d8ec2149 Mon Sep 17 00:00:00 2001
From: Fabio Pistolesi <fabio.pistolesi@forgerock.com>
Date: Fri, 06 Feb 2015 15:43:20 +0000
Subject: [PATCH] OPENDJ-1740 CR-5939 Develop unit tests for pluggable backend and a refactoring on an existing test.
---
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java | 857 ++++++++++++++++++++++++++++++++++++++++++++++++++
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/pluggable/persistit/PersistitTestCase.java | 88 +++++
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/admin/ValidateConfigDefinitionsTest.java | 20
3 files changed, 955 insertions(+), 10 deletions(-)
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/admin/ValidateConfigDefinitionsTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/admin/ValidateConfigDefinitionsTest.java
index ba0438f..b7b0e6c 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/admin/ValidateConfigDefinitionsTest.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/admin/ValidateConfigDefinitionsTest.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2008 Sun Microsystems, Inc.
- * Portions copyright 2011 ForgeRock AS
+ * Portions copyright 2011-2015 ForgeRock AS
*/
package org.opends.server.admin;
@@ -74,10 +74,10 @@
// Exceptions to config objects having a differnt objectclass
private static final List<String> CLASS_OBJECT_CLASS_EXCEPTIONS =
- Arrays.asList(new String[]{
+ Arrays.asList(
"org.opends.server.admin.std.meta.RootCfgDefn",
- "org.opends.server.admin.std.meta.GlobalCfgDefn",
- });
+ "org.opends.server.admin.std.meta.GlobalCfgDefn"
+ );
@Test(dataProvider="enumrateManageObjectDefns")
@@ -114,21 +114,21 @@
// Exceptions to properties ending in -class being exactly 'java-class'.
private static final List<String> CLASS_PROPERTY_EXCEPTIONS =
- Arrays.asList(new String[]{
+ Arrays.asList(
// e.g. "prop-name-ending-with-class"
- });
+ );
// Exceptions to properties ending in -enabled being exactly 'enabled'.
private static final List<String> ENABLED_PROPERTY_EXCEPTIONS =
- Arrays.asList(new String[]{
+ Arrays.asList(
"index-filter-analyzer-enabled",
"subordinate-indexes-enabled"
// e.g. "prop-name-ending-with-enabled"
- });
+ );
// Exceptions to properties not starting with the name of their config object
private static final List<String> OBJECT_PREFIX_PROPERTY_EXCEPTIONS =
- Arrays.asList(new String[]{
+ Arrays.asList(
"backend-id",
"plugin-type",
"replication-server-id",
@@ -137,7 +137,7 @@
"workflow-element-id",
"workflow-element"
// e.g. "prop-name-starting-with-object-prefix"
- });
+ );
private void validatePropertyDefinition(AbstractManagedObjectDefinition<?, ?> objectDef,
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java
new file mode 100644
index 0000000..a2d00ea
--- /dev/null
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java
@@ -0,0 +1,857 @@
+/*
+ * 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");
+ }
+}
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/pluggable/persistit/PersistitTestCase.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/pluggable/persistit/PersistitTestCase.java
new file mode 100644
index 0000000..e087d5c
--- /dev/null
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/pluggable/persistit/PersistitTestCase.java
@@ -0,0 +1,88 @@
+/*
+ * 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.persistit;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertTrue;
+
+import org.forgerock.opendj.config.server.ConfigException;
+import org.opends.server.TestCaseUtils;
+import org.opends.server.admin.std.meta.BackendIndexCfgDefn.IndexType;
+import org.opends.server.admin.std.server.BackendIndexCfg;
+import org.opends.server.admin.std.server.PersistitBackendCfg;
+import org.opends.server.admin.std.server.PluggableBackendCfg;
+import org.opends.server.backends.persistit.PitBackend;
+import org.opends.server.backends.pluggable.PluggableBackendImplTestCase;
+import org.opends.server.core.DirectoryServer;
+import org.testng.annotations.Test;
+
+/**
+ * PersistIt Tester.
+ */
+public class PersistitTestCase extends PluggableBackendImplTestCase
+{
+ @Test
+ public void testPersistitCfg() throws Exception
+ {
+ assertTrue(backend.getRootContainer().isValid());
+ }
+
+ @Override
+ public PitBackend createBackend() throws Exception
+ {
+ PluggableBackendCfg backendCfg = createBackendCfg();
+
+ PitBackend b = new PitBackend();
+ b.setBackendID(backendCfg.getBackendId());
+ b.configureBackend((PersistitBackendCfg)backendCfg);
+ return b;
+ }
+
+ private PluggableBackendCfg createBackendCfg() throws ConfigException
+ {
+ String homeDirName = "pdb_test";
+ PersistitBackendCfg backendCfg = mock(PersistitBackendCfg.class);
+
+ when(backendCfg.getBackendId()).thenReturn("persTest" + homeDirName);
+ when(backendCfg.getDBDirectory()).thenReturn(homeDirName);
+ when(backendCfg.getDBDirectoryPermissions()).thenReturn("755");
+ when(backendCfg.getDBCacheSize()).thenReturn(0L);
+ when(backendCfg.getDBCachePercent()).thenReturn(20);
+ when(backendCfg.isSubordinateIndexesEnabled()).thenReturn(true);
+ when(backendCfg.getBaseDN()).thenReturn(TestCaseUtils.newSortedSet(testBaseDN));
+ when(backendCfg.dn()).thenReturn(testBaseDN);
+ when(backendCfg.listBackendIndexes()).thenReturn(backendIndexes);
+ when(backendCfg.listBackendVLVIndexes()).thenReturn(backendVlvIndexes);
+
+ BackendIndexCfg indexCfg = mock(BackendIndexCfg.class);
+ when(indexCfg.getIndexType()).thenReturn(TestCaseUtils.newSortedSet(IndexType.PRESENCE, IndexType.EQUALITY));
+ when(indexCfg.getAttribute()).thenReturn(DirectoryServer.getAttributeType(backendIndexes[0]));
+ when(backendCfg.getBackendIndex(backendIndexes[0])).thenReturn(indexCfg);
+ return backendCfg;
+ }
+}
--
Gitblit v1.10.0