| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| |
| package org.apache.directory.server.core.partition.ldif; |
| |
| |
| import static org.junit.jupiter.api.Assertions.assertEquals; |
| import static org.junit.jupiter.api.Assertions.assertFalse; |
| import static org.junit.jupiter.api.Assertions.assertNotNull; |
| import static org.junit.jupiter.api.Assertions.assertNull; |
| import static org.junit.jupiter.api.Assertions.assertTrue; |
| import static org.junit.jupiter.api.Assertions.fail; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.RandomAccessFile; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.UUID; |
| |
| import org.apache.directory.api.ldap.model.constants.AuthenticationLevel; |
| import org.apache.directory.api.ldap.model.constants.SchemaConstants; |
| import org.apache.directory.api.ldap.model.csn.CsnFactory; |
| import org.apache.directory.api.ldap.model.entry.Attribute; |
| import org.apache.directory.api.ldap.model.entry.DefaultAttribute; |
| import org.apache.directory.api.ldap.model.entry.DefaultEntry; |
| import org.apache.directory.api.ldap.model.entry.DefaultModification; |
| import org.apache.directory.api.ldap.model.entry.Entry; |
| import org.apache.directory.api.ldap.model.entry.Modification; |
| import org.apache.directory.api.ldap.model.entry.ModificationOperation; |
| import org.apache.directory.api.ldap.model.exception.LdapException; |
| import org.apache.directory.api.ldap.model.exception.LdapOtherException; |
| import org.apache.directory.api.ldap.model.filter.ExprNode; |
| import org.apache.directory.api.ldap.model.filter.FilterParser; |
| import org.apache.directory.api.ldap.model.ldif.LdifEntry; |
| import org.apache.directory.api.ldap.model.ldif.LdifReader; |
| import org.apache.directory.api.ldap.model.ldif.LdifUtils; |
| import org.apache.directory.api.ldap.model.message.SearchScope; |
| import org.apache.directory.api.ldap.model.name.Dn; |
| import org.apache.directory.api.ldap.model.name.Rdn; |
| import org.apache.directory.api.ldap.model.schema.SchemaManager; |
| import org.apache.directory.api.ldap.model.schema.normalizers.ConcreteNameComponentNormalizer; |
| import org.apache.directory.api.ldap.model.schema.normalizers.NameComponentNormalizer; |
| import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor; |
| import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor; |
| import org.apache.directory.api.ldap.schema.loader.LdifSchemaLoader; |
| import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager; |
| import org.apache.directory.api.util.Strings; |
| import org.apache.directory.api.util.exception.Exceptions; |
| import org.apache.directory.server.core.api.CoreSession; |
| import org.apache.directory.server.core.api.DirectoryService; |
| import org.apache.directory.server.core.api.DnFactory; |
| import org.apache.directory.server.core.api.LdapPrincipal; |
| import org.apache.directory.server.core.api.MockCoreSession; |
| import org.apache.directory.server.core.api.MockDirectoryService; |
| import org.apache.directory.server.core.api.entry.ClonedServerEntry; |
| import org.apache.directory.server.core.api.filtering.EntryFilteringCursor; |
| import org.apache.directory.server.core.api.interceptor.context.AddOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.ModDnAva; |
| import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext; |
| import org.apache.directory.server.core.api.normalization.FilterNormalizingVisitor; |
| import org.apache.directory.server.core.api.partition.PartitionTxn; |
| import org.apache.directory.server.core.shared.DefaultDnFactory; |
| import org.junit.jupiter.api.AfterAll; |
| import org.junit.jupiter.api.AfterEach; |
| import org.junit.jupiter.api.BeforeAll; |
| import org.junit.jupiter.api.BeforeEach; |
| import org.junit.jupiter.api.Disabled; |
| import org.junit.jupiter.api.Test; |
| import org.junit.jupiter.api.io.TempDir; |
| |
| |
| /** |
| * Unit test cases for the partition implementation backed by a single LDIF file |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| */ |
| //NOTE: do not use junit concurrent annotations |
| public class SingleFileLdifPartitionTest |
| { |
| private static SchemaManager schemaManager = null; |
| |
| private static DnFactory dnFactory; |
| |
| private static CsnFactory defaultCSNFactory; |
| |
| private static CoreSession mockSession; |
| |
| private static Entry contextEntry; |
| |
| private static LdifReader reader; |
| |
| /** the file in use during the current test method's execution */ |
| private File ldifFileInUse; |
| |
| private SingleFileLdifPartition partition; |
| |
| @TempDir |
| public Path folder; |
| |
| |
| @BeforeAll |
| public static void init() throws Exception |
| { |
| String workingDirectory = System.getProperty( "workingDirectory" ); |
| |
| if ( workingDirectory == null ) |
| { |
| String path = SingleFileLdifPartitionTest.class.getResource( "" ).getPath(); |
| int targetPos = path.indexOf( "target" ); |
| workingDirectory = path.substring( 0, targetPos + 6 ); |
| } |
| |
| File schemaRepository = new File( workingDirectory, "schema" ); |
| SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) ); |
| extractor.extractOrCopy( true ); |
| LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository ); |
| schemaManager = new DefaultSchemaManager( loader ); |
| |
| boolean loaded = schemaManager.loadAllEnabled(); |
| |
| if ( !loaded ) |
| { |
| fail( "Schema load failed : " + Exceptions.printErrors( schemaManager.getErrors() ) ); |
| } |
| |
| reader = new LdifReader( schemaManager ); |
| defaultCSNFactory = new CsnFactory( 0 ); |
| |
| Dn adminDn = new Dn( schemaManager, "uid=admin,ou=system" ); |
| DirectoryService directoryService = new MockDirectoryService( 1 ); |
| directoryService.setSchemaManager( schemaManager ); |
| mockSession = new MockCoreSession( new LdapPrincipal( schemaManager, adminDn, |
| AuthenticationLevel.STRONG ), |
| directoryService ); |
| |
| String contextEntryStr = |
| "dn: ou=test, ou=system\n" + |
| "objectclass: organizationalUnit\n" + |
| "objectclass: top\n" + |
| "ou: test\n" + |
| "entryUUID: 8c7b24a6-1687-461c-88ea-4d30fc234f9b\n" + |
| "entryCSN: 20100919005926.530000Z#000000#000#000000"; |
| |
| LdifEntry ldifEntry = reader.parseLdif( contextEntryStr ).get( 0 ); |
| |
| contextEntry = new ClonedServerEntry( new DefaultEntry( schemaManager, ldifEntry.getEntry() ) ); |
| |
| dnFactory = new DefaultDnFactory( schemaManager, 100 ); |
| } |
| |
| |
| @AfterAll |
| public static void shutdown() throws IOException |
| { |
| reader.close(); |
| } |
| |
| |
| @BeforeEach |
| public void createStore() throws Exception |
| { |
| ldifFileInUse = Files.createFile( folder.resolve( "partition.ldif" ) ).toFile(); |
| } |
| |
| |
| @AfterEach |
| public void deleteStore() throws LdapException |
| { |
| ldifFileInUse.delete(); |
| partition.destroy( partition.beginWriteTransaction() ); |
| } |
| |
| |
| private Entry createEntry( String dn ) throws Exception |
| { |
| Entry entry = new DefaultEntry( schemaManager ); |
| entry.setDn( new Dn( schemaManager, dn ) ); |
| entry.put( SchemaConstants.ENTRY_CSN_AT, defaultCSNFactory.newInstance().toString() ); |
| entry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() ); |
| |
| Entry clonedEntry = new ClonedServerEntry( entry ); |
| |
| return clonedEntry; |
| } |
| |
| |
| private long getEntryLdifLen( Entry entry ) throws LdapException |
| { |
| // Remove the entryDn attribute |
| Entry copy = entry.clone(); |
| copy.removeAttributes( "entryDn" ); |
| |
| // while writing to the file 1 extra newline char will be added |
| |
| String ldif = LdifUtils.convertToLdif( copy ) + "\n"; |
| byte[] data = Strings.getBytesUtf8( ldif ); |
| |
| return data.length; |
| } |
| |
| |
| /** |
| * creates a partition from the given ldif file. If the ldif file name is null |
| * then creates a new file and initializes the partition. If the truncate flag is true |
| * and the given file exists then it erases all the contents of the ldif file before |
| * initializing the partition |
| * |
| * @param fileName the full path to the ldif file to be loaded |
| * @param truncate the flag to determine to truncate the file or not |
| * @return the ldif partition after loading all the data |
| * @throws Exception |
| */ |
| private SingleFileLdifPartition createPartition( String fileName, boolean truncate ) throws Exception |
| { |
| if ( fileName == null ) |
| { |
| fileName = ldifFileInUse.getAbsolutePath(); |
| } |
| |
| if ( truncate ) |
| { |
| RandomAccessFile rf = new RandomAccessFile( fileName, "rws" ); |
| rf.setLength( 0 ); |
| |
| rf.close(); |
| } |
| |
| SingleFileLdifPartition partition = new SingleFileLdifPartition( schemaManager, dnFactory ); |
| partition.setId( "test-ldif" ); |
| partition.setPartitionPath( new File( fileName ).toURI() ); |
| partition.setSuffixDn( new Dn( schemaManager, "ou=test,ou=system" ) ); |
| partition.setSchemaManager( schemaManager ); |
| partition.initialize(); |
| |
| return partition; |
| } |
| |
| |
| private SingleFileLdifPartition reloadPartition() throws Exception |
| { |
| partition.destroy( partition.beginWriteTransaction() ); |
| |
| return createPartition( ldifFileInUse.getAbsolutePath(), false ); |
| } |
| |
| |
| private void assertExists( SingleFileLdifPartition partition, Entry entry ) throws LdapException |
| { |
| LookupOperationContext opCtx = new LookupOperationContext( mockSession, SchemaConstants.ALL_ATTRIBUTES_ARRAY ); |
| opCtx.setDn( entry.getDn() ); |
| opCtx.setPartition( partition ); |
| Entry fetched; |
| |
| try ( PartitionTxn partitionTxn = partition.beginReadTransaction() ) |
| { |
| opCtx.setTransaction( partitionTxn ); |
| |
| fetched = partition.lookup( opCtx ); |
| } |
| catch ( IOException ioe ) |
| { |
| throw new LdapOtherException( ioe.getMessage(), ioe ); |
| } |
| |
| assertNotNull( fetched ); |
| |
| // Check the EntryDn attribute |
| Attribute entryDn = fetched.get( "entryDn" ); |
| |
| assertNotNull( entryDn ); |
| assertEquals( entryDn.getString(), entry.getDn().getName() ); |
| |
| if ( !entry.contains( entryDn ) ) |
| { |
| // Removed the entryDn attribute to be able to compare the entries |
| fetched.removeAttributes( "entryDn" ); |
| } |
| |
| if ( !entry.containsAttribute( SchemaConstants.CONTEXT_CSN_AT ) ) |
| { |
| // Removed the entryDn attribute to be able to compare the entries |
| fetched.removeAttributes( SchemaConstants.CONTEXT_CSN_AT ); |
| } |
| |
| assertEquals( entry, fetched ); |
| } |
| |
| |
| private void assertExists( SingleFileLdifPartition partition, String dn ) throws LdapException |
| { |
| LookupOperationContext opCtx = new LookupOperationContext( mockSession ); |
| opCtx.setDn( new Dn( schemaManager, dn ) ); |
| opCtx.setPartition( partition ); |
| Entry fetched; |
| |
| try ( PartitionTxn partitionTxn = partition.beginReadTransaction() ) |
| { |
| opCtx.setTransaction( partitionTxn ); |
| |
| fetched = partition.lookup( opCtx ); |
| } |
| catch ( IOException ioe ) |
| { |
| throw new LdapOtherException( ioe.getMessage(), ioe ); |
| } |
| |
| assertNotNull( fetched ); |
| } |
| |
| |
| private void assertNotExists( SingleFileLdifPartition partition, Entry entry ) throws LdapException |
| { |
| LookupOperationContext opCtx = new LookupOperationContext( mockSession ); |
| opCtx.setDn( entry.getDn() ); |
| opCtx.setPartition( partition ); |
| Entry fetched; |
| |
| try ( PartitionTxn partitionTxn = partition.beginReadTransaction() ) |
| { |
| opCtx.setTransaction( partitionTxn ); |
| |
| fetched = partition.lookup( opCtx ); |
| } |
| catch ( IOException ioe ) |
| { |
| throw new LdapOtherException( ioe.getMessage(), ioe ); |
| } |
| |
| assertNull( fetched ); |
| } |
| |
| |
| //------------------------------------------------------------------------- |
| // Partition.add() tests |
| //------------------------------------------------------------------------- |
| |
| @Test |
| public void testAddContextEntry() throws Exception |
| { |
| partition = createPartition( null, true ); |
| |
| AddOperationContext addCtx = new AddOperationContext( mockSession ); |
| addCtx.setEntry( contextEntry ); |
| addCtx.setPartition( partition ); |
| addCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.add( addCtx ); |
| |
| String id = partition.getEntryId( partition.beginReadTransaction(), contextEntry.getDn() ); |
| assertNotNull( id ); |
| |
| Entry fetched = partition.fetch( partition.beginReadTransaction(), id ); |
| |
| //remove the entryDn cause it is not present in the above hand made contextEntry |
| fetched.removeAttributes( SchemaConstants.ENTRY_DN_AT ); |
| |
| assertEquals( contextEntry, fetched ); |
| |
| RandomAccessFile file = new RandomAccessFile( new File( partition.getPartitionPath() ), "r" ); |
| |
| assertEquals( getEntryLdifLen( contextEntry ), file.length() ); |
| |
| file.close(); |
| |
| partition = reloadPartition(); |
| assertExists( partition, contextEntry ); |
| } |
| |
| |
| /** |
| * Test some entries creation |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testAddEntries() throws Exception |
| { |
| partition = createPartition( null, true ); |
| |
| AddOperationContext addCtx = new AddOperationContext( mockSession ); |
| addCtx.setEntry( contextEntry ); |
| addCtx.setPartition( partition ); |
| addCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry1 = createEntry( "cn=test,ou=test,ou=system" ); |
| entry1.put( "ObjectClass", "top", "person" ); |
| entry1.put( "cn", "test" ); |
| addCtx.setEntry( entry1 ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry2 = createEntry( "cn=test,cn=test,ou=test,ou=system" ); |
| entry2.put( "ObjectClass", "top", "person" ); |
| entry2.put( "cn", "test" ); |
| addCtx.setEntry( entry2 ); |
| |
| partition.add( addCtx ); |
| |
| Entry entryMvrdn = createEntry( "cn=mvrdn+objectClass=person,cn=test,ou=test,ou=system" ); |
| entryMvrdn.put( "ObjectClass", "top", "person" ); |
| entryMvrdn.put( "cn", "mvrdn" ); |
| addCtx.setEntry( entryMvrdn ); |
| |
| partition.add( addCtx ); |
| |
| partition = reloadPartition(); |
| assertExists( partition, contextEntry ); |
| assertExists( partition, entry1 ); |
| assertExists( partition, entry2 ); |
| assertExists( partition, entryMvrdn ); |
| } |
| |
| |
| /** |
| * Test modifying an entry present at various positions in the LDIF file |
| * 1. Single entry at the start of the file |
| * 2. modify an entry with and without causing the changes to its size |
| * 3.modify an entry present in the middle of the file with increasing/decresing |
| * size |
| * @throws Exception |
| */ |
| @Test |
| public void testModifyEntry() throws Exception |
| { |
| partition = createPartition( null, true ); |
| |
| AddOperationContext addCtx = new AddOperationContext( mockSession ); |
| addCtx.setEntry( contextEntry ); |
| addCtx.setPartition( partition ); |
| addCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.add( addCtx ); |
| |
| ModifyOperationContext modOpCtx = new ModifyOperationContext( mockSession ); |
| modOpCtx.setEntry( contextEntry ); |
| |
| List<Modification> modItems = new ArrayList<Modification>(); |
| |
| Attribute attribute = new DefaultAttribute( schemaManager.lookupAttributeTypeRegistry( "description" ) ); |
| attribute.add( "this is description" ); |
| |
| Modification mod = new DefaultModification(); |
| mod.setOperation( ModificationOperation.ADD_ATTRIBUTE ); |
| mod.setAttribute( attribute ); |
| |
| modItems.add( mod ); |
| modOpCtx.setModItems( modItems ); |
| |
| modOpCtx.setDn( contextEntry.getDn() ); |
| |
| partition.modify( modOpCtx ); |
| RandomAccessFile file = new RandomAccessFile( new File( partition.getPartitionPath() ), "r" ); |
| assertEquals( getEntryLdifLen( modOpCtx.getAlteredEntry() ), file.length() ); |
| |
| // perform the above operation, this time without causing change to the entry's size |
| modOpCtx = new ModifyOperationContext( mockSession ); |
| modOpCtx.setEntry( new ClonedServerEntry( contextEntry ) ); |
| |
| modItems = new ArrayList<Modification>(); |
| |
| attribute = new DefaultAttribute( schemaManager.lookupAttributeTypeRegistry( "description" ) ); |
| attribute.add( "siht si noitpircsed" ); // reversed "this is description" |
| |
| mod = new DefaultModification(); |
| mod.setOperation( ModificationOperation.REPLACE_ATTRIBUTE ); |
| mod.setAttribute( attribute ); |
| |
| modItems.add( mod ); |
| modOpCtx.setModItems( modItems ); |
| |
| modOpCtx.setDn( contextEntry.getDn() ); |
| |
| partition.modify( modOpCtx ); |
| assertEquals( getEntryLdifLen( modOpCtx.getAlteredEntry() ), file.length() ); |
| |
| Entry entry1 = createEntry( "cn=test,ou=test,ou=system" ); |
| entry1.put( "ObjectClass", "top", "person" ); |
| entry1.put( "cn", "test" ); |
| addCtx.setEntry( entry1 ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry2 = createEntry( "cn=test,cn=test,ou=test,ou=system" ); |
| entry2.put( "ObjectClass", "top", "person" ); |
| entry2.put( "cn", "test" ); |
| addCtx.setEntry( entry2 ); |
| |
| partition.add( addCtx ); |
| |
| // now perform a modification on the entry present in middle of LDIF file |
| modOpCtx = new ModifyOperationContext( mockSession ); |
| modOpCtx.setEntry( new ClonedServerEntry( entry1 ) ); |
| modOpCtx.setDn( entry1.getDn() ); |
| |
| modItems = new ArrayList<Modification>(); |
| |
| attribute = new DefaultAttribute( schemaManager.lookupAttributeTypeRegistry( "description" ) ); |
| attribute.add( "desc of entry1" ); // reversed "this is description" |
| |
| mod = new DefaultModification(); |
| mod.setOperation( ModificationOperation.ADD_ATTRIBUTE ); |
| mod.setAttribute( attribute ); |
| |
| modItems.add( mod ); |
| modOpCtx.setModItems( modItems ); |
| |
| partition.modify( modOpCtx ); |
| |
| long ctxEntryLen = getEntryLdifLen( contextEntry ); |
| long entry1Len = getEntryLdifLen( entry1 ); |
| |
| file.seek( ctxEntryLen ); |
| |
| byte[] entry1Data = new byte[( int ) entry1Len]; |
| |
| file.read( entry1Data ); |
| |
| String ldif = Strings.utf8ToString( entry1Data ); |
| |
| LdifEntry ldifEntry = reader.parseLdif( ldif ).get( 0 ); |
| |
| // Remove the EntryDN |
| entry1.removeAttributes( "entryDn" ); |
| |
| assertEquals( entry1, new DefaultEntry( schemaManager, ldifEntry.getEntry() ) ); |
| |
| //"description: desc of entry1\n" |
| |
| modOpCtx = new ModifyOperationContext( mockSession ); |
| modOpCtx.setEntry( new ClonedServerEntry( entry1 ) ); |
| modOpCtx.setDn( entry1.getDn() ); |
| |
| modItems = new ArrayList<Modification>(); |
| |
| attribute = new DefaultAttribute( schemaManager.lookupAttributeTypeRegistry( "description" ) ); |
| attribute.add( "desc of entry1" ); // reversed "this is description" |
| |
| mod = new DefaultModification(); |
| mod.setOperation( ModificationOperation.REMOVE_ATTRIBUTE ); |
| mod.setAttribute( attribute ); |
| |
| modItems.add( mod ); |
| modOpCtx.setModItems( modItems ); |
| |
| partition.modify( modOpCtx ); |
| |
| file.seek( ctxEntryLen ); |
| |
| entry1Len = getEntryLdifLen( entry1 ); |
| entry1Data = new byte[( int ) entry1Len]; |
| |
| file.read( entry1Data ); |
| |
| ldif = Strings.utf8ToString( entry1Data ); |
| |
| ldifEntry = reader.parseLdif( ldif ).get( 0 ); |
| |
| // Remove the EntryDN |
| entry1.removeAttributes( "entryDn" ); |
| |
| assertEquals( entry1, new DefaultEntry( schemaManager, ldifEntry.getEntry() ) ); |
| |
| partition = reloadPartition(); |
| assertExists( partition, contextEntry ); |
| assertExists( partition, entry1 ); |
| assertExists( partition, entry2 ); |
| |
| file.close(); |
| } |
| |
| |
| /** |
| * Test that we can't add an existing entry |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testLdifAddExistingEntry() throws Exception |
| { |
| partition = createPartition( null, true ); |
| |
| AddOperationContext addCtx = new AddOperationContext( mockSession ); |
| addCtx.setEntry( contextEntry ); |
| addCtx.setPartition( partition ); |
| addCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry1 = createEntry( "cn=test,ou=test,ou=system" ); |
| entry1.put( "ObjectClass", "top", "person" ); |
| entry1.put( "cn", "test" ); |
| addCtx.setEntry( entry1 ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry2 = createEntry( "cn=test,cn=test,ou=test,ou=system" ); |
| entry2.put( "ObjectClass", "top", "person" ); |
| entry2.put( "cn", "test" ); |
| addCtx.setEntry( entry2 ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry3 = createEntry( "cn=test,cn=test,ou=test,ou=system" ); |
| entry3.put( "ObjectClass", "top", "person" ); |
| entry3.put( "cn", "test" ); |
| addCtx.setEntry( entry3 ); |
| |
| try |
| { |
| partition.add( addCtx ); |
| fail(); |
| } |
| catch ( LdapException ne ) |
| { |
| assertTrue( true ); |
| } |
| |
| partition = reloadPartition(); |
| assertExists( partition, contextEntry ); |
| assertExists( partition, entry1 ); |
| assertExists( partition, entry2 ); |
| } |
| |
| |
| //------------------------------------------------------------------------- |
| // Partition.delete() tests |
| //------------------------------------------------------------------------- |
| /** |
| * Test that we can delete an existing entry |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testLdifDeleteExistingEntry() throws Exception |
| { |
| partition = createPartition( null, true ); |
| |
| AddOperationContext addCtx = new AddOperationContext( mockSession ); |
| addCtx.setEntry( contextEntry ); |
| addCtx.setPartition( partition ); |
| addCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.add( addCtx ); |
| |
| DeleteOperationContext delOpCtx = new DeleteOperationContext( mockSession ); |
| delOpCtx.setDn( contextEntry.getDn() ); |
| delOpCtx.setPartition( partition ); |
| delOpCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.delete( delOpCtx ); |
| RandomAccessFile file = new RandomAccessFile( new File( partition.getPartitionPath() ), "r" ); |
| |
| assertEquals( 0L, file.length() ); |
| |
| file.close(); |
| |
| addCtx = new AddOperationContext( mockSession ); |
| addCtx.setEntry( contextEntry ); |
| addCtx.setPartition( partition ); |
| addCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry1 = createEntry( "cn=test,ou=test,ou=system" ); |
| entry1.put( "ObjectClass", "top", "person" ); |
| entry1.put( "cn", "test" ); |
| addCtx.setEntry( entry1 ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry2 = createEntry( "cn=test1,cn=test,ou=test,ou=system" ); |
| entry2.put( "ObjectClass", "top", "person" ); |
| entry2.put( "cn", "test1" ); |
| addCtx.setEntry( entry2 ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry3 = createEntry( "cn=test2,cn=test,ou=test,ou=system" ); |
| entry3.put( "ObjectClass", "top", "person" ); |
| entry3.put( "cn", "test2" ); |
| addCtx.setEntry( entry3 ); |
| |
| partition.add( addCtx ); |
| |
| Entry entryMvrdn = createEntry( "cn=mvrdn+objectClass=person,cn=test,ou=test,ou=system" ); |
| entryMvrdn.put( "ObjectClass", "top", "person" ); |
| entryMvrdn.put( "cn", "mvrdn" ); |
| addCtx.setEntry( entryMvrdn ); |
| |
| partition.add( addCtx ); |
| |
| DeleteOperationContext delCtx = new DeleteOperationContext( mockSession ); |
| delCtx.setDn( entryMvrdn.getDn() ); |
| delCtx.setPartition( partition ); |
| delCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.delete( delCtx ); |
| |
| partition = reloadPartition(); |
| assertExists( partition, entry1 ); |
| assertExists( partition, entry2 ); |
| assertExists( partition, entry3 ); |
| } |
| |
| |
| //------------------------------------------------------------------------- |
| // Partition.delete() tests |
| //------------------------------------------------------------------------- |
| /** |
| * Test that we can search for an existing entry |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testLdifSearchExistingEntry() throws Exception |
| { |
| partition = createPartition( null, true ); |
| |
| AddOperationContext addCtx = new AddOperationContext( mockSession ); |
| addCtx.setEntry( contextEntry ); |
| addCtx.setPartition( partition ); |
| addCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry1 = createEntry( "cn=test,ou=test,ou=system" ); |
| entry1.put( "ObjectClass", "top", "person" ); |
| entry1.put( "cn", "test" ); |
| addCtx.setEntry( entry1 ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry2 = createEntry( "cn=test1,cn=test,ou=test,ou=system" ); |
| entry2.put( "ObjectClass", "top", "person" ); |
| entry2.put( "cn", "test1" ); |
| addCtx.setEntry( entry2 ); |
| |
| partition.add( addCtx ); |
| |
| Entry entry3 = createEntry( "cn=test2,cn=test,ou=test,ou=system" ); |
| entry3.put( "ObjectClass", "top", "person" ); |
| entry3.put( "cn", "test2" ); |
| addCtx.setEntry( entry3 ); |
| |
| partition.add( addCtx ); |
| |
| SearchOperationContext searchCtx = new SearchOperationContext( mockSession ); |
| |
| Dn dn = new Dn( schemaManager, "cn=test,ou=test,ou=system" ); |
| searchCtx.setDn( dn ); |
| ExprNode filter = FilterParser.parse( schemaManager, "(ObjectClass=person)" ); |
| NameComponentNormalizer ncn = new ConcreteNameComponentNormalizer( schemaManager ); |
| FilterNormalizingVisitor visitor = new FilterNormalizingVisitor( ncn, schemaManager ); |
| filter.accept( visitor ); |
| searchCtx.setFilter( filter ); |
| searchCtx.setScope( SearchScope.SUBTREE ); |
| |
| try ( PartitionTxn partitionTxn = partition.beginReadTransaction() ) |
| { |
| searchCtx.setPartition( partition ); |
| searchCtx.setTransaction( partitionTxn ); |
| |
| EntryFilteringCursor cursor = partition.search( searchCtx ); |
| |
| assertNotNull( cursor ); |
| |
| Set<Dn> expectedDns = new HashSet<>(); |
| expectedDns.add( entry1.getDn() ); |
| expectedDns.add( entry2.getDn() ); |
| expectedDns.add( entry3.getDn() ); |
| |
| cursor.beforeFirst(); |
| int nbRes = 0; |
| |
| while ( cursor.next() ) |
| { |
| Entry entry = cursor.get(); |
| assertNotNull( entry ); |
| nbRes++; |
| |
| expectedDns.remove( entry.getDn() ); |
| } |
| |
| assertEquals( 3, nbRes ); |
| assertEquals( 0, expectedDns.size() ); |
| |
| cursor.close(); |
| } |
| } |
| |
| |
| @Test |
| public void testLdifMoveEntry() throws Exception |
| { |
| partition = injectEntries(); |
| |
| Entry childEntry1 = partition.fetch( partition.beginReadTransaction(), |
| partition.getEntryId( partition.beginReadTransaction(), new Dn( schemaManager, |
| "cn=child1,ou=test,ou=system" ) ) ); |
| Entry childEntry2 = partition.fetch( partition.beginReadTransaction(), |
| partition.getEntryId( partition.beginReadTransaction(), new Dn( schemaManager, |
| "cn=child2,ou=test,ou=system" ) ) ); |
| |
| MoveOperationContext moveOpCtx = new MoveOperationContext( mockSession, childEntry1.getDn(), |
| childEntry2.getDn() ); |
| moveOpCtx.setPartition( partition ); |
| moveOpCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.move( moveOpCtx ); |
| |
| partition = reloadPartition(); |
| assertExists( partition, childEntry2 ); |
| assertNotExists( partition, childEntry1 ); |
| |
| assertExists( partition, "cn=child1,cn=child2,ou=test,ou=system" ); |
| assertExists( partition, "cn=grandChild11,cn=child1,cn=child2,ou=test,ou=system" ); |
| assertExists( partition, "cn=grandChild12,cn=child1,cn=child2,ou=test,ou=system" ); |
| assertExists( partition, "cn=greatGrandChild111,cn=grandChild11,cn=child1,cn=child2,ou=test,ou=system" ); |
| } |
| |
| |
| @Test |
| public void testLdifMoveSubChildEntry() throws Exception |
| { |
| partition = injectEntries(); |
| |
| Entry childEntry1 = partition.fetch( partition.beginReadTransaction(), |
| partition.getEntryId( partition.beginReadTransaction(), new Dn( schemaManager, |
| "cn=grandChild11,cn=child1,ou=test,ou=system" ) ) ); |
| Entry childEntry2 = partition.fetch( partition.beginReadTransaction(), |
| partition.getEntryId( partition.beginReadTransaction(), new Dn( schemaManager, |
| "cn=child2,ou=test,ou=system" ) ) ); |
| |
| MoveOperationContext moveOpCtx = new MoveOperationContext( mockSession, childEntry1.getDn(), |
| childEntry2.getDn() ); |
| moveOpCtx.setPartition( partition ); |
| moveOpCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.move( moveOpCtx ); |
| |
| partition = reloadPartition(); |
| assertExists( partition, childEntry2 ); |
| assertNotExists( partition, childEntry1 ); |
| |
| assertExists( partition, "cn=child1,ou=test,ou=system" ); |
| assertExists( partition, "cn=child2,ou=test,ou=system" ); |
| assertExists( partition, "cn=grandChild11,cn=child2,ou=test,ou=system" ); |
| assertExists( partition, "cn=grandChild12,cn=child1,ou=test,ou=system" ); |
| assertExists( partition, "cn=greatGrandChild111,cn=grandChild11,cn=child2,ou=test,ou=system" ); |
| } |
| |
| |
| @Test |
| public void testLdifRenameAndDeleteOldRDN() throws Exception |
| { |
| partition = injectEntries(); |
| |
| Dn childDn1 = new Dn( schemaManager, "cn=child1,ou=test,ou=system" ); |
| |
| Rdn newRdn = new Rdn( SchemaConstants.CN_AT + "=" + "renamedChild1" ); |
| RenameOperationContext renameOpCtx = new RenameOperationContext( mockSession, childDn1, newRdn, true ); |
| renameOpCtx.setPartition( partition ); |
| renameOpCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.rename( renameOpCtx ); |
| |
| partition = reloadPartition(); |
| |
| childDn1 = new Dn( schemaManager, "cn=renamedChild1,ou=test,ou=system" ); |
| |
| LookupOperationContext lookupContext = new LookupOperationContext( mockSession, childDn1 ); |
| lookupContext.setPartition( partition ); |
| Entry entry; |
| |
| try ( PartitionTxn partitionTxn = partition.beginReadTransaction() ) |
| { |
| lookupContext.setTransaction( partitionTxn ); |
| |
| entry = partition.lookup( lookupContext ); |
| } |
| catch ( IOException ioe ) |
| { |
| throw new LdapOtherException( ioe.getMessage(), ioe ); |
| } |
| |
| assertNotNull( entry ); |
| assertFalse( entry.get( "cn" ).contains( "child1" ) ); |
| } |
| |
| |
| @Test |
| public void testLdifRenameAndRetainOldRDN() throws Exception |
| { |
| partition = injectEntries(); |
| |
| Dn childDn1 = new Dn( schemaManager, "cn=child1,ou=test,ou=system" ); |
| |
| Rdn newRdn = new Rdn( SchemaConstants.CN_AT + "=" + "renamedChild1" ); |
| RenameOperationContext renameOpCtx = new RenameOperationContext( mockSession, childDn1, newRdn, false ); |
| renameOpCtx.setPartition( partition ); |
| renameOpCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.rename( renameOpCtx ); |
| |
| partition = reloadPartition(); |
| |
| childDn1 = new Dn( schemaManager, "cn=renamedChild1,ou=test,ou=system" ); |
| |
| LookupOperationContext lookupContext = new LookupOperationContext( mockSession, childDn1 ); |
| lookupContext.setPartition( partition ); |
| Entry entry; |
| |
| try ( PartitionTxn partitionTxn = partition.beginReadTransaction() ) |
| { |
| lookupContext.setTransaction( partitionTxn ); |
| |
| entry = partition.lookup( lookupContext ); |
| } |
| catch ( IOException ioe ) |
| { |
| throw new LdapOtherException( ioe.getMessage(), ioe ); |
| } |
| |
| assertNotNull( entry ); |
| assertTrue( entry.get( "cn" ).contains( "child1" ) ); |
| } |
| |
| |
| @Test |
| public void testLdifMoveAndRenameWithDeletingOldRDN() throws Exception |
| { |
| partition = injectEntries(); |
| |
| Dn childDn1 = new Dn( schemaManager, "cn=child1,ou=test,ou=system" ); |
| |
| Dn childDn2 = new Dn( schemaManager, "cn=child2,ou=test,ou=system" ); |
| |
| Rdn newRdn = new Rdn( schemaManager, "cn=movedChild1" ); |
| MoveAndRenameOperationContext moveAndRenameOpCtx = new MoveAndRenameOperationContext( mockSession, childDn1, |
| childDn2, newRdn, true ); |
| |
| LookupOperationContext lookupContext = new LookupOperationContext( mockSession, childDn1 ); |
| lookupContext.setPartition( partition ); |
| Entry originalEntry; |
| |
| try ( PartitionTxn partitionTxn = partition.beginReadTransaction() ) |
| { |
| lookupContext.setTransaction( partitionTxn ); |
| |
| originalEntry = partition.lookup( lookupContext ); |
| } |
| catch ( IOException ioe ) |
| { |
| throw new LdapOtherException( ioe.getMessage(), ioe ); |
| } |
| |
| Entry modifiedEntry = originalEntry.clone(); |
| modifiedEntry.remove( "cn", "child1" ); |
| modifiedEntry.add( "cn", "movedChild1" ); |
| |
| moveAndRenameOpCtx.setEntry( originalEntry ); |
| moveAndRenameOpCtx.setModifiedEntry( modifiedEntry ); |
| moveAndRenameOpCtx.setPartition( partition ); |
| moveAndRenameOpCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| // The dc=movedChild1 RDN that will be added. The dc=child1 Ryan RDN will be removed |
| Map<String, List<ModDnAva>> modDnAvas = new HashMap<>(); |
| |
| List<ModDnAva> modAvas = new ArrayList<>(); |
| modAvas.add( new ModDnAva( ModDnAva.ModDnType.ADD, newRdn.getAva() ) ); |
| modAvas.add( new ModDnAva( ModDnAva.ModDnType.DELETE, childDn1.getRdn().getAva()) ); |
| modDnAvas.put( SchemaConstants.CN_AT_OID, modAvas ); |
| |
| moveAndRenameOpCtx.setModifiedAvas( modDnAvas ); |
| |
| partition.moveAndRename( moveAndRenameOpCtx ); |
| |
| partition = reloadPartition(); |
| |
| childDn1 = new Dn( schemaManager, "cn=movedChild1,cn=child2,ou=test,ou=system" ); |
| |
| lookupContext = new LookupOperationContext( mockSession, childDn1 ); |
| lookupContext.setPartition( partition ); |
| Entry entry; |
| |
| try ( PartitionTxn partitionTxn = partition.beginReadTransaction() ) |
| { |
| lookupContext.setTransaction( partitionTxn ); |
| |
| entry = partition.lookup( lookupContext ); |
| } |
| catch ( IOException ioe ) |
| { |
| throw new LdapOtherException( ioe.getMessage(), ioe ); |
| } |
| |
| assertNotNull( entry ); |
| Attribute dc = entry.get( "cn" ); |
| assertFalse( dc.contains( "child1" ) ); |
| assertTrue( dc.contains( "movedChild1" ) ); |
| } |
| |
| |
| @Test |
| public void testLdifMoveAndRenameRetainingOldRDN() throws Exception |
| { |
| partition = injectEntries(); |
| |
| Dn childDn1 = new Dn( schemaManager, "cn=child1,ou=test,ou=system" ); |
| |
| Dn childDn2 = new Dn( schemaManager, "cn=child2,ou=test,ou=system" ); |
| |
| Rdn newRdn = new Rdn( schemaManager, "cn=movedChild1" ); |
| |
| MoveAndRenameOperationContext moveAndRenameOpCtx = new MoveAndRenameOperationContext( mockSession, childDn1, |
| childDn2, newRdn, true ); |
| |
| LookupOperationContext lookupContext = new LookupOperationContext( mockSession, childDn1 ); |
| lookupContext.setPartition( partition ); |
| Entry originalEntry; |
| |
| try ( PartitionTxn partitionTxn = partition.beginReadTransaction() ) |
| { |
| lookupContext.setTransaction( partitionTxn ); |
| |
| originalEntry = partition.lookup( lookupContext ); |
| } |
| catch ( IOException ioe ) |
| { |
| throw new LdapOtherException( ioe.getMessage(), ioe ); |
| } |
| |
| Entry modifiedEntry = originalEntry.clone(); |
| modifiedEntry.add( "cn", "movedChild1" ); |
| |
| moveAndRenameOpCtx.setEntry( originalEntry ); |
| moveAndRenameOpCtx.setModifiedEntry( modifiedEntry ); |
| |
| // The dc=movedChild1 RDN that will be added. The dc=child1 Ryan RDN will be removed |
| Map<String, List<ModDnAva>> modDnAvas = new HashMap<>(); |
| |
| List<ModDnAva> modAvas = new ArrayList<>(); |
| modAvas.add( new ModDnAva( ModDnAva.ModDnType.ADD, newRdn.getAva() ) ); |
| modDnAvas.put( SchemaConstants.CN_AT_OID, modAvas ); |
| |
| moveAndRenameOpCtx.setModifiedAvas( modDnAvas ); |
| moveAndRenameOpCtx.setPartition( partition ); |
| moveAndRenameOpCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.moveAndRename( moveAndRenameOpCtx ); |
| |
| partition = reloadPartition(); |
| |
| childDn1 = new Dn( schemaManager, "cn=movedChild1,cn=child2,ou=test,ou=system" ); |
| |
| lookupContext = new LookupOperationContext( mockSession, childDn1 ); |
| lookupContext.setPartition( partition ); |
| Entry entry; |
| |
| try ( PartitionTxn partitionTxn = partition.beginReadTransaction() ) |
| { |
| lookupContext.setTransaction( partitionTxn ); |
| |
| entry = partition.lookup( lookupContext ); |
| } |
| catch ( IOException ioe ) |
| { |
| throw new LdapOtherException( ioe.getMessage(), ioe ); |
| } |
| |
| assertNotNull( entry ); |
| Attribute cn = entry.get( "cn" ); |
| assertTrue( cn.contains( "child1" ) ); |
| assertTrue( cn.contains( "movedchild1" ) ); |
| } |
| |
| |
| @Test |
| public void testEnableRewritingFlag() throws Exception |
| { |
| partition = createPartition( null, true ); |
| |
| // disable writing |
| partition.setEnableRewriting( partition.beginReadTransaction(), false ); |
| |
| AddOperationContext addCtx = new AddOperationContext( mockSession ); |
| addCtx.setEntry( contextEntry ); |
| addCtx.setPartition( partition ); |
| addCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.add( addCtx ); |
| |
| // search works fine |
| String id = partition.getEntryId( partition.beginReadTransaction(), contextEntry.getDn() ); |
| assertNotNull( id ); |
| |
| Entry fetched = partition.fetch( partition.beginReadTransaction(), id ); |
| |
| //remove the entryDn cause it is not present in the above hand made contextEntry |
| fetched.removeAttributes( SchemaConstants.ENTRY_DN_AT ); |
| |
| assertEquals( contextEntry, fetched ); |
| |
| RandomAccessFile file = new RandomAccessFile( new File( partition.getPartitionPath() ), "r" ); |
| |
| // but the file will be empty |
| assertFalse( getEntryLdifLen( contextEntry ) == file.length() ); |
| |
| partition = reloadPartition(); |
| assertNotExists( partition, contextEntry ); |
| |
| // try adding on the reloaded partition |
| partition.add( addCtx ); |
| |
| // eable writing, this will let the partition write data back to disk |
| partition.setEnableRewriting( partition.beginReadTransaction(), false ); |
| assertTrue( getEntryLdifLen( contextEntry ) == file.length() ); |
| |
| file.close(); |
| } |
| |
| |
| /** |
| * An important test to check the stability of the partition |
| * under high concurrency |
| * |
| * @throws Exception |
| */ |
| @Test |
| @Disabled("Taking way too much time and very timing dependent") |
| public void testConcurrentOperations() throws Exception |
| { |
| partition = injectEntries(); |
| |
| ThreadGroup tg = new ThreadGroup( "singlefileldifpartitionTG" ); |
| |
| Thread modifyTask = new Thread( tg, getModifyTask( partition ), "modifyTaskThread" ); |
| Thread addAndDeleteTask = new Thread( tg, getAddAndDeleteTask( partition ), "addAndDeleteTaskThread" ); |
| Thread renameTask = new Thread( tg, getRenameTask( partition ), "renameTaskThread" ); |
| Thread moveTask = new Thread( tg, getMoveTask( partition ), "moveTaskThread" ); |
| |
| modifyTask.start(); |
| addAndDeleteTask.start(); |
| renameTask.start(); |
| moveTask.start(); |
| |
| while ( tg.activeCount() > 0 ) |
| { |
| Thread.sleep( 2000 ); |
| } |
| |
| // tests to be performed after the threads finish their work |
| partition = reloadPartition(); |
| |
| // test the work of modify thread |
| LookupOperationContext lookupContext = new LookupOperationContext( mockSession ); |
| lookupContext.setDn( new Dn( "cn=threadDoModify,ou=test,ou=system" ) ); |
| lookupContext.setPartition( partition ); |
| Entry entry; |
| |
| try ( PartitionTxn partitionTxn = partition.beginReadTransaction() ) |
| { |
| lookupContext.setTransaction( partitionTxn ); |
| |
| entry = partition.lookup( lookupContext ); |
| } |
| catch ( IOException ioe ) |
| { |
| throw new LdapOtherException( ioe.getMessage(), ioe ); |
| } |
| |
| assertNotNull( entry ); |
| assertEquals( "description no 999", entry.get( "description" ).getString() ); |
| assertExists( partition, contextEntry.getDn().getName() ); |
| assertExists( partition, "cn=child1,ou=test,ou=system" ); |
| assertExists( partition, "cn=child2,ou=test,ou=system" ); |
| assertExists( partition, "cn=grandChild11,cn=child1,ou=test,ou=system" ); |
| assertExists( partition, "cn=grandChild12,cn=child1,ou=test,ou=system" ); |
| assertExists( partition, "cn=greatGrandChild111,cn=grandChild11,cn=child1,ou=test,ou=system" ); |
| } |
| |
| |
| /** |
| * add and keep modifying an attribute's value for 1000 times |
| */ |
| private Runnable getModifyTask( final SingleFileLdifPartition partition ) |
| { |
| Runnable r = new Runnable() |
| { |
| |
| public void run() |
| { |
| int i = 0; |
| |
| try |
| { |
| AddOperationContext addCtx = new AddOperationContext( mockSession ); |
| |
| Entry childEntry1 = createEntry( "cn=threadDoModify,ou=test,ou=system" ); |
| childEntry1.put( "ObjectClass", "top", "person" ); |
| childEntry1.put( "cn", "threadDoModify" ); |
| addCtx.setEntry( childEntry1 ); |
| partition.add( addCtx ); |
| |
| ModifyOperationContext modOpCtx = new ModifyOperationContext( mockSession ); |
| modOpCtx.setEntry( childEntry1 ); |
| |
| List<Modification> modItems = new ArrayList<Modification>(); |
| |
| Attribute attribute = new DefaultAttribute( |
| schemaManager.lookupAttributeTypeRegistry( "description" ) ); |
| |
| Modification mod = new DefaultModification(); |
| mod.setOperation( ModificationOperation.REPLACE_ATTRIBUTE ); |
| mod.setAttribute( attribute ); |
| |
| modItems.add( mod ); |
| modOpCtx.setModItems( modItems ); |
| |
| modOpCtx.setDn( childEntry1.getDn() ); |
| |
| for ( ; i < 1000; i++ ) |
| { |
| attribute.clear(); |
| attribute.add( "description no " + i ); |
| partition.modify( modOpCtx ); |
| } |
| } |
| catch ( Exception e ) |
| { |
| e.printStackTrace(); |
| fail( "error while running ModifyTask at iteration count " + i ); |
| } |
| |
| } |
| |
| }; |
| |
| return r; |
| } |
| |
| |
| /** |
| * adds and deletes the same entry 1000 times |
| */ |
| private Runnable getAddAndDeleteTask( final SingleFileLdifPartition partition ) |
| { |
| Runnable r = new Runnable() |
| { |
| |
| public void run() |
| { |
| int i = 0; |
| |
| try |
| { |
| AddOperationContext addCtx = new AddOperationContext( mockSession ); |
| DeleteOperationContext deleteCtx = new DeleteOperationContext( mockSession ); |
| |
| for ( ; i < 1000; i++ ) |
| { |
| Entry entry = createEntry( "cn=threadDoAddAndDelete,ou=test,ou=system" ); |
| entry.put( "ObjectClass", "top", "person" ); |
| entry.put( "cn", "threadDoAddAndDelete" ); |
| addCtx.setEntry( entry ); |
| |
| // add first |
| partition.add( addCtx ); |
| |
| // then delete, net affect on the count of entries at the end is zero |
| deleteCtx.setDn( entry.getDn() ); |
| partition.delete( deleteCtx ); |
| } |
| } |
| catch ( Exception e ) |
| { |
| e.printStackTrace(); |
| fail( "error while running AddAndDeleteTask at iteration count " + i ); |
| } |
| } |
| |
| }; |
| |
| return r; |
| |
| } |
| |
| |
| /** |
| * performs rename operation on an entry 1000 times, at the end of the |
| * last iteration the original entry should remain with the old Dn it has |
| * before starting this method |
| */ |
| private Runnable getRenameTask( final SingleFileLdifPartition partition ) |
| { |
| Runnable r = new Runnable() |
| { |
| public void run() |
| { |
| int i = 0; |
| |
| try |
| { |
| Dn dn = new Dn( schemaManager, "cn=grandChild12,cn=child1,ou=test,ou=system" ); |
| |
| Rdn oldRdn = new Rdn( SchemaConstants.CN_AT + "=" + "grandChild12" ); |
| |
| Rdn newRdn = new Rdn( SchemaConstants.CN_AT + "=" + "renamedGrandChild12" ); |
| |
| Dn tmpDn = dn; |
| Rdn tmpRdn = newRdn; |
| |
| for ( ; i < 500; i++ ) |
| { |
| RenameOperationContext renameOpCtx = new RenameOperationContext( mockSession, tmpDn, tmpRdn, |
| true ); |
| |
| partition.rename( renameOpCtx ); |
| tmpDn = dn.getParent(); |
| tmpDn = tmpDn.add( newRdn ); |
| tmpRdn = oldRdn; |
| |
| renameOpCtx = new RenameOperationContext( mockSession, tmpDn, tmpRdn, true ); |
| partition.rename( renameOpCtx ); |
| tmpDn = dn; |
| tmpRdn = newRdn; |
| } |
| } |
| catch ( Exception e ) |
| { |
| e.printStackTrace(); |
| fail( "error while running RenameTask at iteration count " + i ); |
| } |
| } |
| |
| }; |
| |
| return r; |
| } |
| |
| |
| /** |
| * performs move operation on an entry 1000 times, at the end of the |
| * last iteration the original entry should remain at the place where it |
| * was before starting this method |
| */ |
| private Runnable getMoveTask( final SingleFileLdifPartition partition ) |
| { |
| Runnable r = new Runnable() |
| { |
| |
| public void run() |
| { |
| int i = 0; |
| |
| try |
| { |
| Dn originalDn = new Dn( schemaManager, "cn=grandChild11,cn=child1,ou=test,ou=system" ); |
| |
| Dn originalParent = new Dn( schemaManager, "cn=child1,ou=test,ou=system" ); |
| Dn newParent = new Dn( schemaManager, "cn=child2,ou=test,ou=system" ); |
| |
| Dn tmpDn = originalDn; |
| Dn tmpParentDn = newParent; |
| |
| for ( ; i < 500; i++ ) |
| { |
| MoveOperationContext moveOpCtx = new MoveOperationContext( mockSession, tmpDn, tmpParentDn ); |
| partition.move( moveOpCtx ); |
| tmpDn = moveOpCtx.getNewDn(); |
| tmpParentDn = originalParent; |
| |
| moveOpCtx = new MoveOperationContext( mockSession, tmpDn, tmpParentDn ); |
| partition.move( moveOpCtx ); |
| tmpDn = moveOpCtx.getNewDn(); |
| tmpParentDn = newParent; |
| } |
| } |
| catch ( Exception e ) |
| { |
| e.printStackTrace(); |
| fail( "error while running MoveTask at iteration count " + i ); |
| } |
| } |
| |
| }; |
| |
| return r; |
| } |
| |
| |
| private SingleFileLdifPartition injectEntries() throws Exception |
| { |
| SingleFileLdifPartition partition = createPartition( null, true ); |
| AddOperationContext addCtx = new AddOperationContext( mockSession ); |
| addCtx.setEntry( contextEntry ); |
| addCtx.setPartition( partition ); |
| addCtx.setTransaction( partition.beginWriteTransaction() ); |
| |
| partition.add( addCtx ); |
| |
| Entry childEntry1 = createEntry( "cn=child1,ou=test,ou=system" ); |
| childEntry1.put( "ObjectClass", "top", "person" ); |
| childEntry1.put( "cn", "child1" ); |
| childEntry1.put( "sn", "child1" ); |
| addCtx.setEntry( childEntry1 ); |
| |
| partition.add( addCtx ); |
| |
| Entry childEntry2 = createEntry( "cn=child2,ou=test,ou=system" ); |
| childEntry2.put( "ObjectClass", "top", "person" ); |
| childEntry2.put( "cn", "child2" ); |
| childEntry1.put( "sn", "child2" ); |
| addCtx.setEntry( childEntry2 ); |
| |
| partition.add( addCtx ); |
| |
| Entry grandChild11 = createEntry( "cn=grandChild11,cn=child1,ou=test,ou=system" ); |
| grandChild11.put( "ObjectClass", "top", "person" ); |
| grandChild11.put( "cn", "grandChild11" ); |
| childEntry1.put( "sn", "grandChild11" ); |
| addCtx.setEntry( grandChild11 ); |
| |
| partition.add( addCtx ); |
| |
| Entry grandChild12 = createEntry( "cn=grandChild12,cn=child1,ou=test,ou=system" ); |
| grandChild12.put( "ObjectClass", "top", "person" ); |
| grandChild12.put( "cn", "grandChild12" ); |
| childEntry1.put( "sn", "grandChild12" ); |
| addCtx.setEntry( grandChild12 ); |
| |
| partition.add( addCtx ); |
| |
| Entry greatGrandChild111 = createEntry( "cn=greatGrandChild111,cn=grandChild11,cn=child1,ou=test,ou=system" ); |
| greatGrandChild111.put( "ObjectClass", "top", "person" ); |
| greatGrandChild111.put( "cn", "greatGrandChild111" ); |
| greatGrandChild111.put( "sn", "greatGrandChild111" ); |
| addCtx.setEntry( greatGrandChild111 ); |
| |
| partition.add( addCtx ); |
| |
| return partition; |
| } |
| } |