/* * 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)); } }