/*
|
* 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 2006-2010 Sun Microsystems, Inc.
|
* Portions Copyright 2011-2015 ForgeRock AS
|
*/
|
package org.opends.server.backends.jeb;
|
|
import static org.opends.server.util.ServerConstants.*;
|
import static org.testng.Assert.*;
|
|
import java.util.HashMap;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
|
import org.forgerock.opendj.ldap.ByteString;
|
import org.opends.server.TestCaseUtils;
|
import org.opends.server.api.Backend;
|
import org.opends.server.backends.VerifyConfig;
|
import org.opends.server.core.DirectoryServer;
|
import org.opends.server.types.*;
|
import org.opends.server.util.StaticUtils;
|
import org.testng.annotations.AfterClass;
|
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.DataProvider;
|
import org.testng.annotations.Test;
|
|
import com.sleepycat.je.DatabaseEntry;
|
import com.sleepycat.je.DatabaseException;
|
import com.sleepycat.je.LockMode;
|
import com.sleepycat.je.OperationStatus;
|
import com.sleepycat.je.Transaction;
|
|
@SuppressWarnings("javadoc")
|
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 backendID = "verifyRoot";
|
private String numUsersLine="define numusers= #numEntries#";
|
private DN[] baseDNs;
|
private Backend<?> backend;
|
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(backendID);
|
baseDNs = new DN[] {
|
DN.valueOf(suffix)
|
};
|
}
|
|
@AfterClass
|
public void cleanUp() throws Exception {
|
TestCaseUtils.clearJEBackend(backendID);
|
TestCaseUtils.disableBackend(backendID);
|
}
|
|
/**
|
* Performs a complete 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]);
|
backend = DirectoryServer.getBackend(backendID);
|
assertEquals(backend.verifyBackend(verifyConfig), 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");
|
backend = DirectoryServer.getBackend(backendID);
|
assertEquals(backend.verifyBackend(verifyConfig), 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);
|
backend = DirectoryServer.getBackend(backendID);
|
assertEquals(backend.verifyBackend(verifyConfig), 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.valueOf(junkDN);
|
EntryID id=new EntryID(45);
|
assertTrue(dn2id.insert(txn, testDN, id));
|
//Make two DN keys point at same entry.
|
testDN=DN.valueOf(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.valueOf(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).getEqualityIndex();
|
//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);
|
assertEquals(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);
|
AttributeType[] types = vlvIndex.getSortTypes();
|
|
// Add an incorrectly ordered values.
|
SortValuesSet svs =
|
vlvIndex.getSortValuesSet(null, 0, new ByteString[3], new AttributeType[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), types);
|
|
// Add an invalid ID
|
svs2.add(1000, vlvIndex.getSortValues(entry), types);
|
|
// Muck up the values of another ID
|
id = svs.getEntryIDs()[0];
|
entry = eContainer.getID2Entry().get(null, new EntryID(id), LockMode.DEFAULT);
|
ByteString[] values = vlvIndex.getSortValues(entry);
|
ByteString[] badValues = new ByteString[values.length];
|
System.arraycopy(values, 1, badValues, 0, values.length - 1);
|
badValues[badValues.length-1] = values[0];
|
remove(svs, id, values);
|
svs.add(id, badValues, types);
|
|
putSortValuesSet(vlvIndex, svs);
|
putSortValuesSet(vlvIndex, 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 = buildEntry(junkDN);
|
DataConfig dataConfig = new DataConfig(false, false, null);
|
ByteString entryBytes = ID2Entry.entryToDatabase(testEntry, dataConfig);
|
DatabaseEntry data= new DatabaseEntry(entryBytes.toByteArray());
|
assertEquals(id2entry.put(txn, key, data), OperationStatus.SUCCESS);
|
|
// add entry with random 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.valueOf(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.valueOf(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.
|
AttributeIndex attributeIndex = eContainer.getAttributeIndex(attributeType);
|
Index eqIndex = attributeIndex.getEqualityIndex();
|
Index presIndex = attributeIndex.getPresenceIndex();
|
Index subIndex = attributeIndex.getSubstringIndex();
|
Index ordIndex = attributeIndex.getOrderingIndex();
|
//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);
|
assertEquals(status, OperationStatus.SUCCESS);
|
status = ordIndex.put(txn, key, data);
|
assertEquals(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);
|
assertEquals(status, OperationStatus.SUCCESS);
|
status = ordIndex.put(txn, key, data);
|
assertEquals(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);
|
assertEquals(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);
|
assertEquals(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);
|
AttributeType[] types = vlvIndex.getSortTypes();
|
|
// Remove an ID
|
SortValuesSet svs = vlvIndex.getSortValuesSet(null, 0, new ByteString[3], types);
|
long id = svs.getEntryIDs()[0];
|
Entry entry = eContainer.getID2Entry().get(null, new EntryID(id), LockMode.DEFAULT);
|
remove(svs, id, vlvIndex.getSortValues(entry));
|
|
// Add an incorrectly ordered values.
|
SortValuesSet svs2 = svs.split(2);
|
svs2.add(1000, vlvIndex.getSortValues(entry), types);
|
|
// Muck up the values of another ID
|
id = svs.getEntryIDs()[0];
|
entry = eContainer.getID2Entry().get(null, new EntryID(id), LockMode.DEFAULT);
|
ByteString[] values = vlvIndex.getSortValues(entry);
|
ByteString[] badValues = new ByteString[values.length];
|
System.arraycopy(values, 1, badValues, 0, values.length - 1);
|
badValues[badValues.length-1] = values[0];
|
remove(svs, id, values);
|
svs.add(id, badValues, types);
|
|
putSortValuesSet(vlvIndex, svs);
|
putSortValuesSet(vlvIndex, svs2);
|
performBECompleteVerify("vlv." + indexName, 3);
|
}
|
finally
|
{
|
eContainer.sharedLock.unlock();
|
}
|
}
|
|
private void remove(SortValuesSet svs, long id, ByteString[] values) throws DirectoryException
|
{
|
svs.remove(new SortValues(new EntryID(id), values, new SortOrder()));
|
}
|
|
/**
|
* Put a sort values set in this VLV index.
|
*
|
* @param txn
|
* The transaction to use when retrieving the set or NULL if it is
|
* not required.
|
* @param sortValuesSet
|
* The SortValuesSet to put.
|
* @return True if the sortValuesSet was put successfully or False otherwise.
|
* @throws JebException
|
* If an error occurs during an operation on a JE database.
|
* @throws DatabaseException
|
* If an error occurs during an operation on a JE database.
|
* @throws DirectoryException
|
* If a Directory Server error occurs.
|
*/
|
private void putSortValuesSet(VLVIndex vlvIndex, SortValuesSet sortValuesSet) throws JebException, DirectoryException
|
{
|
DatabaseEntry key = new DatabaseEntry(sortValuesSet.getKeyBytes());
|
DatabaseEntry data = new DatabaseEntry(sortValuesSet.toDatabase());
|
vlvIndex.put(null, key, data);
|
}
|
|
/* 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");
|
backend = DirectoryServer.getBackend(backendID);
|
assertEquals(backend.verifyBackend(verifyConfig), 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);
|
backend = DirectoryServer.getBackend(backendID);
|
backend.verifyBackend(verifyConfig);
|
}
|
|
/* 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 = buildEntry(dn);
|
DataConfig dataConfig = new DataConfig(false, false, null);
|
byte []entryBytes = ID2Entry.entryToDatabase(testEntry, dataConfig).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);
|
}
|
assertEquals(backend.verifyBackend(verifyConfig), 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);
|
backend = DirectoryServer.getBackend(backendID);
|
RootContainer rContainer = ((BackendImpl) backend).getRootContainer();
|
eContainer= rContainer.getEntryContainer(DN.valueOf(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(backendID);
|
template[2]=numUsersLine;
|
template[2]=
|
template[2].replaceAll("#numEntries#", String.valueOf(numEntries));
|
createLoadEntries(template, numEntries);
|
}
|
|
/**
|
* Builds an entry.
|
*
|
* @param dn to put into the entry.
|
* @return a new entry.
|
* @throws DirectoryException if the entry cannot be created.
|
*/
|
private Entry buildEntry(String dn) throws DirectoryException {
|
DN entryDN = DN.valueOf(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));
|
}
|
}
|