PluggableBackendImplTestCase.java revision 870930ab008b106540456b3efe47e7ec613c174d
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2015 ForgeRock AS
*/
/**
* BackendImpl Tester.
*/
@SuppressWarnings("javadoc")
public abstract class PluggableBackendImplTestCase<C extends PluggableBackendCfg> extends DirectoryServerTestCase
{
protected BackendImpl<C> backend;
protected DN testBaseDN;
protected DN badEntryDN;
protected String[] ldifTemplate;
protected int ldifNumberOfEntries;
{
backendIndexes.put("sn", new IndexType[] { IndexType.PRESENCE, IndexType.EQUALITY, IndexType.SUBSTRING });
};
private AttributeType modifyAttribute;
private String backupPath;
private BackupDirectory backupDirectory;
/**
* Factory method for creating a new unconfigured backend instance.
*
* @return the unconfigured backend instance.
* @see #setUp()
*/
protected abstract BackendImpl<C> createBackend();
/**
* Factory method for creating a new backend configuration. All methods specific to the sub-class
* should be stubbed out.
*
* @return the new backend configuration.
* @see #setUp()
*/
protected abstract C createBackendCfg();
{
// Need the schema to be available, so make sure the server is started.
C backendCfg = createBackendCfg();
{
}
backend = createBackend();
"dn: " + testBaseDN,
"objectclass: top",
"objectclass: domain",
"",
"dn: ou=People," + testBaseDN,
"objectclass: top",
"objectclass: organizationalUnit",
"ou: People");
"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.");
"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.");
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 branch entries
ldifNumberOfEntries += 2;
}
{
try
{
if (backupDirectory != null)
{
}
}
catch (DirectoryException ignore)
{
/*
* Due to test sequencing (Import, backup, restore, export) in case of intermediate failure
* Backup may or may not be present. -> ignore.
*/
}
finally
{
}
}
/**
* Tests the storage API for resource checking. The tested method has no return value, but an
* exception, while not systematic, may be thrown, in which case the test must fail.
*
* @throws Exception
* if resources are low.
*/
@Test
public void testCheckForEnoughResources() throws Exception
{
}
@Test
{
}
/**
* Helper for add entries in a backend.
* @throws Exception
*/
{
{
}
}
public void testAddNoParent() throws Exception
{
}
public void testUtilityAPIs()
{
{
{
final AttributeType attributeType = DirectoryServer.getAttributeTypeOrNull(index.getKey().toLowerCase());
}
}
}
private int getTotalNumberOfLDIFEntries()
{
}
public void testHasSubordinates() throws Exception
{
"Base DN should have subordinates.");
// Testing ConditionResult.UNDEFINED needs either no entry container or a big DIT...
"Subordinates query on unknown baseDN should return UNDEFINED.");
assertEquals(backend.getNumberOfEntriesInBaseDN(testBaseDN), getTotalNumberOfLDIFEntries(), "Wrong DIT count.");
"Leaf entry should not have any subordinates.");
}
private List<SearchResultEntry> runSearch(SearchRequest request, boolean useInternalConnection) throws Exception
{
{
return search.getSearchEntries();
}
else
{
return search.getSearchEntries();
}
}
@Test(dependsOnMethods = { "testAdd", "testModifyEntry", "testRenameEntry", "testDeleteAlreadyDeletedEntry" })
public void testBaseSearch() throws Exception
{
baseSearch(false);
baseSearch(true);
}
{
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);
}
{
"One Level search should return the expected child");
}
@Test(dependsOnMethods = { "testAdd", "testModifyEntry", "testRenameEntry", "testDeleteAlreadyDeletedEntry" })
public void testSubTreeSearch() throws Exception
{
subTreeSearch(false);
subTreeSearch(true);
}
@Test(dependsOnMethods = { "testAdd", "testModifyEntry", "testRenameEntry", "testDeleteAlreadyDeletedEntry" })
public void testSubTreeSearchAgainstAnIndexWithUnrecognizedMatchingRule() throws Exception
{
}
public void testSearchIsConsideredUnindexedBasedOnLookThroughLimit() throws DirectoryException {
final SearchRequest request = newSearchRequest(testBaseDN, SearchScope.WHOLE_SUBTREE, "objectclass=*");
InternalSearchOperation searchOperation = new InternalSearchOperation(connection, 1, 1, request, null);
assertThat(searchOperation.getErrorMessage().toString()).contains("not have sufficient privileges", "unindexed search");
}
{
// Sum of all entry sets minus a delete
"Subtree search should return a correct number of entries");
}
protected Object[][] userEntrySearchData()
{
return new Object[][] {
// @formatter:off
// @formatter:on
};
}
dependsOnMethods = { "testAdd", "testModifyEntry", "testRenameEntry", "testDeleteAlreadyDeletedEntry" })
public void testUserEntrySearch(boolean useInternalConnection, SearchScope scope, int expectedEntryCount)
throws Exception
{
assertEquals(result.size(), expectedEntryCount, "User entry search should return " + expectedEntryCount
+ " child entry");
if (expectedEntryCount > 0)
{
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
{
}
{
{
}
return result;
}
{
}
public void testRenameEntry() throws Exception
{
// Move the entire subtree to another name and move it back.
}
public void testModifyEntry() throws Exception
{
newEntry.applyModifications(Arrays.asList(new Modification(ADD, create(modifyAttribute, modifyValue))));
}
@Test(dependsOnMethods = { "testAdd", "testRenameEntry", "testHasSubordinates", "testUtilityAPIs" })
public void testDeleteEntry() throws Exception
{
}
public void testDeleteAlreadyDeletedEntry() throws Exception
{
try
{
fail("Should have generated a DirectoryException");
}
catch (DirectoryException de)
{
// Expected exception, do nothing, test succeeds.
}
}
{
}
@Test(dependsOnMethods = { "testBaseSearch", "testOneLevelSearch", "testSubTreeSearch", "testUserEntrySearch" })
public void testImportLDIF() throws Exception
{
// Import wants the backend to be configured but not initialized. Finalizing resets the status.
System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT) + File.separator + "resource" + File.separator
+ "MakeLDIF";
{
importConf.setInvokeImportPlugins(true);
importConf.setClearBackend(true);
importConf.setSkipDNValidation(true);
}
/** +1 for the testBaseDN itself */
assertEquals(backend.getNumberOfEntriesInBaseDN(testBaseDN), ldifNumberOfEntries, "Not enough entries in DIT.");
/** -2 for baseDn and People entry */
assertEquals(backend.getNumberOfChildren(testBaseDN.child(DN.valueOf("ou=People"))), ldifNumberOfEntries - 2, "Not enough entries in DIT.");
{
}
config = new VerifyConfig();
{
}
}
public void testRebuildAllIndex() throws Exception
{
final EntryContainer entryContainer = backend.getRootContainer().getEntryContainers().iterator().next();
// Delete all the indexes
{
{
{
}
{
{
}
}
}
});
{
}
config = new VerifyConfig();
{
}
}
public void testRebuildDegradedIndex() throws Exception
{
final EntryContainer entryContainer = backend.getRootContainer().getEntryContainers().iterator().next();
final Set<String> dirtyIndexes = new HashSet<>(Arrays.asList(new String[] { "sn", "uid", "telephoneNumber" }));
// Delete all the indexes
{
{
{
{
}
}
}
});
{
}
config = new VerifyConfig();
{
}
// Put back the backend in its original state for the following tests
// backend.openBackend();
}
public void testVerifyID2ChildrenCount() throws Exception
{
final ID2ChildrenCount id2ChildrenCount = backend.getRootContainer().getEntryContainer(testBaseDN).getID2ChildrenCount();
// Insert an error
{
{
}
});
{
{
}
});
}
public void testBackup() throws Exception
{
}
public void testRestore() throws Exception
{
}
public void testExportLDIF() throws Exception
{
{
}
}
public void testReadOnly() throws Exception
{
C backendCfg = createBackendCfg();
final Storage storage = backend.configureStorage(backendCfg, DirectoryServer.getInstance().getServerContext());
final RootContainer readOnlyContainer = new RootContainer(backend.getBackendID(), storage, backendCfg);
// Put backend offline so that export LDIF open read-only container
try
{
{
{
txn.put(new TreeName("dc=test,dc=com", "id2entry"), ByteString.valueOfUtf8("key"), ByteString.valueOfUtf8("value"));
}
});
}
finally
{
}
}
}