/*
* 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-2010 Sun Microsystems, Inc.
* Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.backends.jeb;
import org.opends.server.core.DirectoryServer;
import org.opends.server.TestCaseUtils;
import org.opends.server.types.*;
import org.opends.server.util.StaticUtils;
import static org.opends.server.util.ServerConstants.OC_TOP;
import static org.opends.server.util.ServerConstants.OC_EXTENSIBLE_OBJECT;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.AfterClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.Transaction;
import com.sleepycat.je.LockMode;
import java.util.*;
public class TestVerifyJob extends JebTestCase
{
//Root suffix for verify backend
private static String suffix="dc=verify,dc=jeb";
private static String vBranch="ou=verify tests," + suffix;
private String beID="verifyRoot";
private String numUsersLine="define numusers= #numEntries#";
//Attribute type in stat entry containing error count
private String errorCount="verify-error-count";
private DN[] baseDNs;
private BackendImpl be;
private EntryContainer eContainer;
private DN2ID dn2id;
private ID2Entry id2entry;
private Index id2child;
private Index id2subtree;
private Transaction txn;
//Some DNs needed mostly for DN2ID tests
private String junkDN="cn=junk," + vBranch;
private String junkDN1="cn=junk1," + vBranch;
private String junkDN2="cn=junk2," + vBranch;
private String junkDN3="cn=junk3," + vBranch;
//This DN has no parent
private String noParentDN="cn=junk1,cn=junk22," + vBranch;
//Parent child combo for id2child/subtree type tests
private String pDN="cn=junk222," + vBranch;
private String cDN="cn=junk4,cn=junk222," + vBranch;
//Bad DN
private String badDN="this is a bad DN";
//This index file should not exist
private String badIndexName="badIndexName";
@DataProvider(name = "indexes")
public Object[][] indexes() {
return new Object[][] {
{ "telephoneNumber"},
{"givenName"},
{ "id2subtree"},
{"id2children"},
{"dn2id"}
};
}
private static String[] template = new String[] {
"define suffix="+suffix,
"define maildomain=example.com",
"define numusers= #numEntries#",
"",
"branch: [suffix]",
"",
"branch: " + vBranch,
"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}.",
""};
@BeforeClass
public void setup() throws Exception {
TestCaseUtils.startServer();
TestCaseUtils.enableBackend(beID);
baseDNs = new DN[] {
DN.decode(suffix)
};
}
@AfterClass
public void cleanUp() throws Exception {
TestCaseUtils.clearJEBackend(false, beID, suffix);
TestCaseUtils.disableBackend(beID);
}
/**
* Performs a ncomplete verify against a backend using the
* entries loaded in the setup initializer.
*
* @throws Exception if error count is not equal to 0.
*/
@Test()
public void testCompleteVerifyJob() throws Exception {
cleanAndLoad(9);
VerifyConfig verifyConfig = new VerifyConfig();
verifyConfig.setBaseDN(baseDNs[0]);
Entry statEntry=bldStatEntry("");
be=(BackendImpl) DirectoryServer.getBackend(beID);
be.verifyBackend(verifyConfig, statEntry);
assertEquals(getStatEntryCount(statEntry, errorCount), 0);
}
/**
* Adds more than "entry limit" number of entries and runs clean
* verify against two indexes.
*
* @throws Exception if error count is not equal to 0.
*/
@Test()
public void testEntryLimitVerifyJob() throws Exception {
cleanAndLoad(25);
VerifyConfig verifyConfig = new VerifyConfig();
verifyConfig.setBaseDN(baseDNs[0]);
verifyConfig.addCleanIndex("telephoneNumber");
verifyConfig.addCleanIndex("givenName");
Entry statEntry=bldStatEntry("");
be=(BackendImpl) DirectoryServer.getBackend(beID);
be.verifyBackend(verifyConfig, statEntry);
assertEquals(getStatEntryCount(statEntry, errorCount), 0);
}
/**
* Runs clean verify jobs against a set of indexes (defined in
* indexes array).
* @param index An element of the indexes array.
* @throws Exception if the error count is not equal to 0.
*/
@Test(dataProvider = "indexes")
public void testCleanVerifyJob(String index) throws Exception {
cleanAndLoad(9);
VerifyConfig verifyConfig = new VerifyConfig();
verifyConfig.setBaseDN(baseDNs[0]);
verifyConfig.addCleanIndex(index);
Entry statEntry=bldStatEntry("");
be=(BackendImpl) DirectoryServer.getBackend(beID);
be.verifyBackend(verifyConfig, statEntry);
assertEquals(getStatEntryCount(statEntry, errorCount), 0);
}
/*
* Begin Clean index tests. These are tests that cursor through an index
* file and validate it's keys and idlists against the id2entry database entries.
* The complete index tests go the other way. They cursor the id2entry database
* and validate each entry against the various index files.
*/
/**
* Runs clean verify against the dn2id index after adding
* various errors in that index file.
*
* @throws Exception if the error count is not equal to 5.
*/
@Test()
public void testCleanDN2ID() throws Exception {
preTest(3);
eContainer.sharedLock.lock();
try
{
//Add a junk DN and non-existent entry id to DN2ID index
DN testDN=DN.decode(junkDN);
EntryID id=new EntryID(45);
assertTrue(dn2id.insert(txn, testDN, id));
//Make two DN keys point at same entry.
testDN=DN.decode(junkDN1);
id=new EntryID(3);
assertTrue(dn2id.insert(txn, testDN, id));
//Add badDN key with bad entry id
DatabaseEntry key=
new DatabaseEntry(StaticUtils.getBytes(badDN));
DatabaseEntry data =
new EntryID(37).getDatabaseEntry();
assertEquals(dn2id.put(txn, key, data), OperationStatus.SUCCESS);
//Add DN key with malformed entryID
key=new DatabaseEntry(StaticUtils.getBytes(junkDN2));
data= new DatabaseEntry(new byte[3]);
assertEquals(dn2id.put(txn, key, data), OperationStatus.SUCCESS);
//Try to break JebFormat version
addID2EntryReturnKey(junkDN3, 20, true);
id=new EntryID(20);
assertTrue(dn2id.insert(txn, DN.decode(junkDN3), id));
performBECleanVerify("dn2id", 5);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/**
* Runs clean verify against the id2children index after adding
* various errors in that index file.
*
* @throws Exception if the error count is not equal to 6.
*/
@Test() public void testCleanID2Children() throws Exception {
preTest(3);
eContainer.sharedLock.lock();
try
{
//Add malformed key
byte[] shortBytes = new byte[3];
DatabaseEntry key= new DatabaseEntry(shortBytes);
EntryIDSet idSet=new EntryIDSet();
id2child.writeKey(txn, key, idSet);
//Try to break JebFormat version of key entry
key=addID2EntryReturnKey(junkDN, 4, true);
idSet=new EntryIDSet(new byte[16], new byte[16]);
id2child.writeKey(txn, key, idSet);
//put invalid key -- no EntryID matches
key= new EntryID(45).getDatabaseEntry();
id2child.writeKey(txn, key, idSet);
//invalid ids in id list
key=addID2EntryReturnKey(junkDN1, 5, false);
byte[] idBytes=new byte[24];
//doesn't exist
idBytes[3] = (byte)0xff;
//not a child
idBytes[15] = (byte)1;
//bad jeb format
idBytes[23] = (byte) 0x04;
idSet=new EntryIDSet(null, idBytes);
id2child.writeKey(txn, key, idSet);
performBECleanVerify("id2children", 6);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/**
* Runs clean verify against the id2subtree index after adding
* various errors in that index file.
*
* @throws Exception if the error count is not equal to 7.
*/
@Test() public void testCleanID2Subtree() throws Exception {
preTest(4);
eContainer.sharedLock.lock();
try
{
//break key
byte[] shortBytes = new byte[3];
DatabaseEntry key= new DatabaseEntry(shortBytes);
EntryIDSet idSet=new EntryIDSet();
id2subtree.writeKey(txn, key, idSet);
//put invalid ids into entry 3 idlist
key= new EntryID(3).getDatabaseEntry();
byte[] idBytes=new byte[16];
//invalid id
idBytes[3] = (byte)0xff;
//non-subordinate
idBytes[15] = (byte)1;
idSet=new EntryIDSet(null, idBytes);
id2subtree.writeKey(txn, key, idSet);
//Try to break JebFormat version of key entry
key=addID2EntryReturnKey(junkDN, 4, true);
idBytes[3]=(byte) 0x04;
idBytes[15]=(byte)0x00;
EntryIDSet idSet1=new EntryIDSet(null, idBytes);
id2subtree.writeKey(txn, key, idSet1);
//put invalid key -- no EntryID matches
key= new EntryID(45).getDatabaseEntry();
idSet=new EntryIDSet(null, idBytes);
id2subtree.writeKey(txn, key, idSet);
performBECleanVerify("id2subtree", 7);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/**
* Runs clean verify against the telephoneNumber.equality index
* after adding various errors in that index file.
*
* @throws Exception if the error count is not equal to 4.
*/
@Test() public void testCleanAttrIndex() throws Exception {
String phoneType="telephonenumber";
preTest(3);
eContainer.sharedLock.lock();
try
{
AttributeType attributeType =
DirectoryServer.getAttributeType(phoneType);
Index index =
eContainer.getAttributeIndex(attributeType).equalityIndex;
//Add entry with bad JEB format Version
addID2EntryReturnKey(junkDN, 4, true);
//Add phone number with various bad id list entryIDs
byte[] subBytes = StaticUtils.getBytes("0009999999");
DatabaseEntry key= new DatabaseEntry(subBytes);
byte[] dataBytes=new byte[32];
//put duplicate ids in list
dataBytes[7] = (byte)1;
dataBytes[15] = (byte)1;
//put id that doesn't exist
dataBytes[23] = (byte)0xff;
//point to bad entry added above
dataBytes[31] = (byte) 0x04;
DatabaseEntry data= new DatabaseEntry(dataBytes);
OperationStatus status = index.put(txn, key, data);
assertTrue(status == OperationStatus.SUCCESS);
//really 5 errors, but duplicate reference doesn't increment error
//count for some reason
performBECleanVerify(phoneType, 4);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/**
* Runs clean verify against the testvlvindex VLV index
* after adding various errors to each of these index files.
* @throws Exception if the error count is not equal to 6.
*/
@Test() public void testCleanVLV() throws Exception {
String indexName = "testvlvindex";
preTest(4);
eContainer.sharedLock.lock();
try
{
VLVIndex vlvIndex = eContainer.getVLVIndex(indexName);
// Add an incorrectly ordered values.
SortValuesSet svs =
vlvIndex.getSortValuesSet(null, 0, new AttributeValue[3]);
long id = svs.getEntryIDs()[0];
Entry entry = eContainer.getID2Entry().get(null, new EntryID(id), LockMode.DEFAULT);
SortValuesSet svs2 = svs.split(2);
svs2.add(id, vlvIndex.getSortValues(entry));
// Add an invalid ID
svs2.add(1000, vlvIndex.getSortValues(entry));
// Muck up the values of another ID
id = svs.getEntryIDs()[0];
entry = eContainer.getID2Entry().get(null, new EntryID(id), LockMode.DEFAULT);
AttributeValue[] values = vlvIndex.getSortValues(entry);
AttributeValue[] badValues = new AttributeValue[values.length];
System.arraycopy(values, 1, badValues, 0, values.length - 1);
badValues[badValues.length-1] = values[0];
svs.remove(id, values);
svs.add(id, badValues);
vlvIndex.putSortValuesSet(null, svs);
vlvIndex.putSortValuesSet(null, svs2);
performBECleanVerify("vlv." + indexName, 3);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/*
* Begin complete verify index tests. As described above, these are
* tests that cursor through the id2entry database and validate
* each entry against the various index files.
*
*/
/**
* Runs complete verify against the telephoneNumber index
* after adding various errors in the id2entry file.
*
* @throws Exception if the error count is not equal to 3.
*/
@Test() public void testVerifyID2Entry() throws Exception {
preTest(3);
eContainer.sharedLock.lock();
try
{
//Add entry with short id
byte[] shortBytes = new byte[3];
DatabaseEntry key= new DatabaseEntry(shortBytes);
Entry testEntry=bldStatEntry(junkDN);
ByteString entryBytes =
ID2Entry.entryToDatabase(testEntry,
new DataConfig(false, false, null));
DatabaseEntry data= new DatabaseEntry(entryBytes.toByteArray());
assertEquals(id2entry.put(txn, key, data), OperationStatus.SUCCESS);
//add entry with ramdom bytes
DatabaseEntry key1= new EntryID(4).getDatabaseEntry();
byte []eBytes = new byte[459];
for(int i=0;i<459;i++) {
eBytes[i]=(byte) (i*2);
}
//set version correctly
eBytes[0]=0x01;
DatabaseEntry data1= new DatabaseEntry(eBytes);
assertEquals(id2entry.put(txn, key1, data1), OperationStatus.SUCCESS);
performBECompleteVerify("telephoneNumber", 3);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/**
*
* Runs complete verify against the dn2id index
* after adding various errors in the dn2id file.
*
* @throws Exception if the error count is not equal to 3.
*/
@Test() public void testVerifyDN2ID() throws Exception {
preTest(9);
eContainer.sharedLock.lock();
try
{
//add entry but no corresponding dn2id key
addID2EntryReturnKey(junkDN, 10, false);
//entry has dn2id key but its entryID -- don't need key
addID2EntryReturnKey(junkDN1, 11, false);
//insert key with bad entry id (45 instead of 10)
DN testDN=DN.decode(junkDN1);
EntryID id=new EntryID(45);
assertTrue(dn2id.insert(txn, testDN, id));
//entry has no parent in dn2id
addID2EntryReturnKey(noParentDN, 12, false);
//add the key/id
testDN=DN.decode(noParentDN);
id=new EntryID(12);
assertTrue(dn2id.insert(txn, testDN, id));
performBECompleteVerify("dn2id", 3);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/**
*
* Runs complete verify against the id2children index
* after adding various errors in the id2children file.
*
* @throws Exception if the error count is not equal to 3.
*/
@Test() public void testVerifyID2Children() throws Exception {
preTest(9);
eContainer.sharedLock.lock();
try
{
//Add dn with no parent
DatabaseEntry key=addID2EntryReturnKey(noParentDN, 10, false);
byte[] idBytes=new byte[16];
idBytes[7]=(byte) 0x0A;
EntryIDSet idSet=new EntryIDSet(null, idBytes);
id2child.writeKey(txn, key, idSet);
//Add child entry - don't worry about key
addID2EntryReturnKey(cDN, 11, false);
//Add its parent entry -- need the key
DatabaseEntry keyp=addID2EntryReturnKey(pDN, 12, false);
//add parent key/IDSet with bad IDset id
byte[] idBytesp=new byte[16];
idBytesp[7]=(byte) 0xFF;
EntryIDSet idSetp=new EntryIDSet(null, idBytesp);
id2child.writeKey(txn, keyp, idSetp);
performBECompleteVerify("id2children", 3);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/**
*
* Runs complete verify against the id2children index
* after adding various errors in the id2children file.
* This is a second test because the key needed to have
* null idlist. This test is really just for coverage and
* should have a 0 error count.
*
* @throws Exception if the error count is not equal to 0.
*/
@Test() public void testVerifyID2Children1() throws Exception {
preTest(2);
eContainer.sharedLock.lock();
try
{
//Add child entry - don't worry about key
addID2EntryReturnKey(pDN, 10, false);
//add parent key/IDSet with null keyset
EntryIDSet idSetp=new EntryIDSet();
DatabaseEntry key= new EntryID(2).getDatabaseEntry();
id2child.writeKey(txn, key, idSetp);
performBECompleteVerify("id2children", 0);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/**
*
* Runs complete verify against the id2subtree index
* after adding various errors in the id2subtree file.
*
* @throws Exception if the error count is not equal to 3.
*/
@Test
public void testVerifyID2Subtree() throws Exception {
preTest(2);
eContainer.sharedLock.lock();
try
{
//Add entry with no parent
addID2EntryReturnKey(noParentDN, 3, false);
performBECompleteVerify("id2subtree", 3);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/**
*
* Runs complete verify against the id2subtree index
* after adding various errors in the id2subtree file.
* This is a second test because the key needed to have
* null idlist.
*
* @throws Exception if the error count is not equal to 1.
*/
@Test
public void testVerifyID2Subtree1() throws Exception {
preTest(2);
eContainer.sharedLock.lock();
try
{
//Add child entry - don't worry about key
addID2EntryReturnKey(pDN, 3, false);
//add parent key/IDSet with null keyset
EntryIDSet idSet=new EntryIDSet();
DatabaseEntry key= new EntryID(2).getDatabaseEntry();
id2subtree.writeKey(txn, key, idSet);
performBECompleteVerify("id2subtree", 1);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/**
* Runs complete verify against the mail indexes
* (equality, presence, substring, ordering)
* after adding various errors to each of these index files.
* @throws Exception if the error count is not equal to 6.
*/
@Test() public void testVerifyAttribute() throws Exception {
String mailType="mail";
preTest(4);
eContainer.sharedLock.lock();
try
{
AttributeType attributeType =
DirectoryServer.getAttributeType(mailType);
//Get db handles to each index.
Index eqIndex =
eContainer.getAttributeIndex(attributeType).equalityIndex;
Index presIndex =
eContainer.getAttributeIndex(attributeType).presenceIndex;
Index subIndex =
eContainer.getAttributeIndex(attributeType).substringIndex;
Index ordIndex =
eContainer.getAttributeIndex(attributeType).orderingIndex;
//Add invalid idlist ids to both equality and ordering indexes.
DatabaseEntry key=
new DatabaseEntry(StaticUtils.getBytes("user.0@example.com"));
byte[] dataBytes=new byte[16];
//put duplicate ids in list
dataBytes[7] = (byte)0xff;
dataBytes[15] = (byte)0xfe;
DatabaseEntry data= new DatabaseEntry(dataBytes);
OperationStatus status = eqIndex.put(txn, key, data);
assertTrue(status == OperationStatus.SUCCESS);
status = ordIndex.put(txn, key, data);
assertTrue(status == OperationStatus.SUCCESS);
//Add null idlist to both equality and ordering indexes.
key =
new DatabaseEntry(StaticUtils.getBytes("user.1@example.com"));
data= new DatabaseEntry(new EntryIDSet().toDatabase());
status = eqIndex.put(txn, key, data);
assertTrue(status == OperationStatus.SUCCESS);
status = ordIndex.put(txn, key, data);
assertTrue(status == OperationStatus.SUCCESS);
//Add invalid idlist ids to presence index.
key =
new DatabaseEntry(StaticUtils.getBytes("+"));
data = new DatabaseEntry(dataBytes);
status = presIndex.put(txn, key, data);
assertTrue(status == OperationStatus.SUCCESS);
//Add invalid idlist ids to substring index.
key =
new DatabaseEntry(StaticUtils.getBytes("@examp"));
data = new DatabaseEntry(dataBytes);
status = subIndex.put(txn, key, data);
assertTrue(status == OperationStatus.SUCCESS);
performBECompleteVerify(mailType, 6);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/**
* Runs complete verify against the testvlvindex VLV index
* after adding various errors to each of these index files.
* @throws Exception if the error count is not equal to 6.
*/
@Test() public void testVerifyVLV() throws Exception {
String indexName = "testvlvindex";
preTest(4);
eContainer.sharedLock.lock();
try
{
VLVIndex vlvIndex = eContainer.getVLVIndex(indexName);
// Remove an ID
SortValuesSet svs =
vlvIndex.getSortValuesSet(null, 0, new AttributeValue[3]);
long id = svs.getEntryIDs()[0];
Entry entry = eContainer.getID2Entry().get(null, new EntryID(id), LockMode.DEFAULT);
svs.remove(id, vlvIndex.getSortValues(entry));
// Add an incorrectly ordered values.
SortValuesSet svs2 = svs.split(2);
svs2.add(1000, vlvIndex.getSortValues(entry));
// Muck up the values of another ID
id = svs.getEntryIDs()[0];
entry = eContainer.getID2Entry().get(null, new EntryID(id), LockMode.DEFAULT);
AttributeValue[] values = vlvIndex.getSortValues(entry);
AttributeValue[] badValues = new AttributeValue[values.length];
System.arraycopy(values, 1, badValues, 0, values.length - 1);
badValues[badValues.length-1] = values[0];
svs.remove(id, values);
svs.add(id, badValues);
vlvIndex.putSortValuesSet(null, svs);
vlvIndex.putSortValuesSet(null, svs2);
performBECompleteVerify("vlv." + indexName, 3);
}
finally
{
eContainer.sharedLock.unlock();
}
}
/* Various tests not either clean or complete */
/**
* Try to verify a non-indexed attribute.
* @throws Exception if error count is not equal to 0.
*/
@Test(expectedExceptions=Exception.class)
public void testVerifyNotIndexed() throws Exception {
cleanAndLoad(2);
VerifyConfig verifyConfig = new VerifyConfig();
verifyConfig.setBaseDN(baseDNs[0]);
verifyConfig.addCleanIndex("userPassword");
Entry statEntry=bldStatEntry("");
be=(BackendImpl) DirectoryServer.getBackend(beID);
be.verifyBackend(verifyConfig, statEntry);
assertEquals(getStatEntryCount(statEntry, errorCount), 0);
}
/**
* Try to verify an nonexistent attribute.
* @throws Exception if verify backend fails.
*/
@Test(expectedExceptions=Exception.class)
public void testInvalidIndex() throws Exception {
cleanAndLoad(2);
VerifyConfig verifyConfig = new VerifyConfig();
verifyConfig.setBaseDN(baseDNs[0]);
verifyConfig.addCleanIndex(badIndexName);
Entry statEntry=bldStatEntry("");
be=(BackendImpl) DirectoryServer.getBackend(beID);
be.verifyBackend(verifyConfig, statEntry);
}
/* end tests */
/**
* Adds an entry to the id2entry database with a dn and id passed into the
* method. Optional flag to set the Jeb version byte for those types of tests.
* @param dn the dn string to put in the entry.
* @param id to use as the id2entry key,
* @param trashFormat true if first byte should be changed to invalid value.
* @return Database entry key of the entry.
* @throws Exception if the entry is not added to the id2entry database.
*/
private DatabaseEntry addID2EntryReturnKey(String dn, long id, boolean trashFormat)
throws Exception {
DatabaseEntry key= new EntryID(id).getDatabaseEntry();
Entry testEntry=bldStatEntry(dn);
byte []entryBytes =
ID2Entry.entryToDatabase(testEntry,
new DataConfig(false, false, null)).toByteArray();
if(trashFormat)
entryBytes[0] = 0x67;
DatabaseEntry data= new DatabaseEntry(entryBytes);
assertEquals(id2entry.put(txn, key, data), OperationStatus.SUCCESS);
return key;
}
/**
* Wrapper to do a clean verify.
* @param indexToDo index file to run verify against.
* @param expectedErrors number of errors expected for this test.
* @throws Exception if the verify fails.
*/
private void performBECleanVerify(String indexToDo,
int expectedErrors) throws Exception {
performBEVerify(indexToDo, expectedErrors, true);
}
/**
* Wrapper to do a complete verify.
* @param indexToDo index file to run verify against.
* @param expectedErrors number of errors expected for this test.
* @throws Exception if the verify fails.
*/
private void performBECompleteVerify(String indexToDo,
int expectedErrors) throws Exception {
performBEVerify(indexToDo, expectedErrors, false);
}
/**
* Performs either a clean or complete verify depending on
* flag passed in.
*
* @param indexToDo index file to run verify against.
* @param expectedErrors number of errors expected for this test.
* @param clean do clean verify if true.
* @throws Exception if the verify fails.
*/
private void performBEVerify(String indexToDo,
int expectedErrors, boolean clean) throws Exception {
EntryContainer.transactionCommit(txn);
VerifyConfig verifyConfig = new VerifyConfig();
verifyConfig.setBaseDN(baseDNs[0]);
if(!clean)
verifyConfig.addCompleteIndex(indexToDo);
else
verifyConfig.addCleanIndex(indexToDo);
Entry statEntry=bldStatEntry("");
be.verifyBackend(verifyConfig, statEntry);
assertEquals(getStatEntryCount(statEntry, errorCount), expectedErrors);
}
/**
* Does a pretest setup. Creates some number of entries, gets
* backend, rootcontainer, entryContainer objects, as well as
* various index objects.
* Also starts a transaction.
* @param numEntries number of entries to add to the verify backend.
* @throws Exception if entries cannot be loaded.
*/
private void preTest(int numEntries) throws Exception {
cleanAndLoad(numEntries);
be=(BackendImpl) DirectoryServer.getBackend(beID);
RootContainer rContainer = be.getRootContainer();
eContainer= rContainer.getEntryContainer(DN.decode(suffix));
id2child=eContainer.getID2Children();
id2entry=eContainer.getID2Entry();
id2subtree=eContainer.getID2Subtree();
dn2id=eContainer.getDN2ID();
txn = eContainer.beginTransaction();
}
/**
* Cleans verify backend and loads some number of entries.
* @param numEntries number of entries to load into the backend.
* @throws Exception if the entries are not loaded or created.
*/
private void cleanAndLoad(int numEntries) throws Exception {
TestCaseUtils.clearJEBackend(false, beID, suffix);
template[2]=numUsersLine;
template[2]=
template[2].replaceAll("#numEntries#", String.valueOf(numEntries));
createLoadEntries(template, numEntries);
}
/**
* Gets information from the stat entry and returns that value as a Long.
* @param e entry to search.
* @param type attribute type
* @return Long
* @throws NumberFormatException if the attribute value cannot be parsed.
*/
private long getStatEntryCount(Entry e, String type)
throws NumberFormatException {
AttributeType attrType =
DirectoryServer.getAttributeType(type);
if (attrType == null)
attrType = DirectoryServer.getDefaultAttributeType(type);
List<Attribute> attrList = e.getAttribute(attrType, null);
AttributeValue v = attrList.get(0).iterator().next();
long retVal = Long.parseLong(v.getValue().toString());
return (retVal);
}
/**
* Builds an entry suitable for using in the verify job to gather statistics about
* the verify.
* @param dn to put into the entry.
* @return a suitable entry.
* @throws DirectoryException if the cannot be created.
*/
private Entry bldStatEntry(String dn) throws DirectoryException {
DN entryDN = DN.decode(dn);
HashMap<ObjectClass, String> ocs = new HashMap<ObjectClass, String>(2);
ObjectClass topOC = DirectoryServer.getObjectClass(OC_TOP);
if (topOC == null) {
topOC = DirectoryServer.getDefaultObjectClass(OC_TOP);
}
ocs.put(topOC, OC_TOP);
ObjectClass extensibleObjectOC = DirectoryServer
.getObjectClass(OC_EXTENSIBLE_OBJECT);
if (extensibleObjectOC == null) {
extensibleObjectOC = DirectoryServer
.getDefaultObjectClass(OC_EXTENSIBLE_OBJECT);
}
ocs.put(extensibleObjectOC, OC_EXTENSIBLE_OBJECT);
return new Entry(entryDN, ocs,
new LinkedHashMap<AttributeType, List<Attribute>>(0),
new HashMap<AttributeType, List<Attribute>>(0));
}
}