Added a test to check that adding or deleting entries while doing a
search does not result in some error. (see DIRSERVER-2049)
diff --git a/core-integ/src/test/java/org/apache/directory/server/core/operations/search/SearchWithAddDelete.java b/core-integ/src/test/java/org/apache/directory/server/core/operations/search/SearchWithAddDelete.java
new file mode 100644
index 0000000..5657849
--- /dev/null
+++ b/core-integ/src/test/java/org/apache/directory/server/core/operations/search/SearchWithAddDelete.java
@@ -0,0 +1,281 @@
+/*
+ *  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.operations.search;
+
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.message.AliasDerefMode;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.server.core.annotations.ContextEntry;
+import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreateIndex;
+import org.apache.directory.server.core.annotations.CreatePartition;
+import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.apache.directory.server.core.integ.IntegrationUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Tests the search() method with Delete done in the middle
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(FrameworkRunner.class)
+@CreateDS(
+    name = "SearchAddDS",
+    partitions =
+        {
+            @CreatePartition(
+                cacheSize = 12000,
+                name = "example",
+                suffix = "dc=example,dc=com",
+                contextEntry = @ContextEntry(
+                    entryLdif =
+                    "dn: dc=example,dc=com\n" +
+                        "dc: example\n" +
+                        "objectClass: top\n" +
+                        "objectClass: domain\n\n"),
+                indexes =
+                    {
+                        @CreateIndex(attribute = "objectClass", cacheSize = 2000),
+                        @CreateIndex(attribute = "sn", cacheSize = 2000),
+                        @CreateIndex(attribute = "cn", cacheSize = 2000),
+                        @CreateIndex(attribute = "displayName", cacheSize = 2000)
+                })
+
+    },
+    enableChangeLog = false)
+public class SearchWithAddDelete extends AbstractLdapTestUnit
+{
+    @Test
+    public void testSearchWithDeletion() throws Exception
+    {
+        LdapConnection connection = IntegrationUtils.getAdminConnection( getService() );
+        connection.bind( "uid=admin,ou=system", "secret" );
+
+        Entry rootPeople = new DefaultEntry(
+            connection.getSchemaManager(),
+            "ou=People,dc=example,dc=com",
+            "objectClass: top",
+            "objectClass: organizationalUnit",
+            "ou: People" );
+
+        connection.add( rootPeople );
+        int nbUsers = 1000;
+
+        for ( int i = 0; i < nbUsers; i++ )
+        {
+            Entry user = new DefaultEntry(
+                connection.getSchemaManager(),
+                "uid=user." + i + ",ou=People,dc=example,dc=com",
+                "objectClass: top",
+                "objectClass: person",
+                "objectClass: organizationalPerson",
+                "objectClass: inetOrgPerson",
+                "givenName: Aaccf",
+                "sn: Amar",
+                "cn", "user" + i,
+                "initials: AA",
+                "uid", "user." + i,
+                "mail: user.1@cs.hacettepe.edu.tr",
+                "userPassword: password",
+                "telephoneNumber: 314-796-3178",
+                "homePhone: 514-847-0518",
+                "pager: 784-600-5445",
+                "mobile: 801-755-4931",
+                "street: 00599 First Street",
+                "l: Augusta",
+                "st: MN",
+                "postalCode: 30667",
+                "postalAddress: Aaccf Amar$00599 First Street$Augusta, MN  30667",
+                "description: This is the description for Aaccf Amar." );
+
+            try
+            {
+                connection.add( user );
+            }
+            catch ( NullPointerException npe )
+            {
+                System.out.println( i );
+                npe.printStackTrace();
+                throw npe;
+            }
+        }
+
+        // Now do some search
+        SearchRequest searchRequest = new SearchRequestImpl();
+
+        searchRequest.setBase( new Dn( "ou=people,dc=example,dc=com" ) );
+        searchRequest.setScope( SearchScope.SUBTREE );
+        searchRequest.addAttributes( "*" );
+        searchRequest.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );
+        searchRequest.setFilter( "(objectClass=*)" );
+        int count = 0;
+
+        try ( SearchCursor cursor = connection.search( searchRequest ) )
+        {
+            while ( cursor.next() )
+            {
+                cursor.getEntry();
+                
+                count++;
+                
+                if ( count == 300 )
+                {
+                    // Now delete 90 entries while doing a search
+                    for ( int j = 10; j <100; j++ )
+                    {
+                        connection.delete( "uid=user." + j + ",ou=People,dc=example,dc=com" );
+                    }
+                }
+            }
+        }
+        
+        // Deletion of entries while doing a search should result in a smaller result set 
+        assertTrue( count < nbUsers + 1 );
+        connection.close();
+    }
+    
+    
+    @Test
+    public void testSearchWithAddition() throws Exception
+    {
+        LdapConnection connection = IntegrationUtils.getAdminConnection( getService() );
+        connection.bind( "uid=admin,ou=system", "secret" );
+
+        Entry rootPeople = new DefaultEntry(
+            connection.getSchemaManager(),
+            "ou=People,dc=example,dc=com",
+            "objectClass: top",
+            "objectClass: organizationalUnit",
+            "ou: People" );
+
+        connection.add( rootPeople );
+        int nbUsers = 1000;
+
+        for ( int i = 0; i < nbUsers; i++ )
+        {
+            Entry user = new DefaultEntry(
+                connection.getSchemaManager(),
+                "uid=user." + i + ",ou=People,dc=example,dc=com",
+                "objectClass: top",
+                "objectClass: person",
+                "objectClass: organizationalPerson",
+                "objectClass: inetOrgPerson",
+                "givenName: Aaccf",
+                "sn: Amar",
+                "cn", "user" + i,
+                "initials: AA",
+                "uid", "user." + i,
+                "mail: user.1@cs.hacettepe.edu.tr",
+                "userPassword: password",
+                "telephoneNumber: 314-796-3178",
+                "homePhone: 514-847-0518",
+                "pager: 784-600-5445",
+                "mobile: 801-755-4931",
+                "street: 00599 First Street",
+                "l: Augusta",
+                "st: MN",
+                "postalCode: 30667",
+                "postalAddress: Aaccf Amar$00599 First Street$Augusta, MN  30667",
+                "description: This is the description for Aaccf Amar." );
+
+            try
+            {
+                connection.add( user );
+            }
+            catch ( NullPointerException npe )
+            {
+                System.out.println( i );
+                npe.printStackTrace();
+                throw npe;
+            }
+        }
+
+        // Now do some search
+        SearchRequest searchRequest = new SearchRequestImpl();
+
+        searchRequest.setBase( new Dn( "ou=people,dc=example,dc=com" ) );
+        searchRequest.setScope( SearchScope.SUBTREE );
+        searchRequest.addAttributes( "*" );
+        searchRequest.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );
+        searchRequest.setFilter( "(objectClass=*)" );
+        int count = 0;
+
+        try ( SearchCursor cursor = connection.search( searchRequest ) )
+        {
+            while ( cursor.next() )
+            {
+                cursor.getEntry();
+                
+                count++;
+                
+                if ( count == 300 )
+                {
+                    // Now delete 90 entries while doing a search
+                    for ( int j = 2000; j <2100; j++ )
+                    {
+                        Entry user = new DefaultEntry(
+                            connection.getSchemaManager(),
+                            "uid=user." + j + ",ou=People,dc=example,dc=com",
+                            "objectClass: top",
+                            "objectClass: person",
+                            "objectClass: organizationalPerson",
+                            "objectClass: inetOrgPerson",
+                            "givenName: Aaccf",
+                            "sn: Amar",
+                            "cn", "user" + j,
+                            "initials: AA",
+                            "uid", "user." + j,
+                            "mail: user.1@cs.hacettepe.edu.tr",
+                            "userPassword: password",
+                            "telephoneNumber: 314-796-3178",
+                            "homePhone: 514-847-0518",
+                            "pager: 784-600-5445",
+                            "mobile: 801-755-4931",
+                            "street: 00599 First Street",
+                            "l: Augusta",
+                            "st: MN",
+                            "postalCode: 30667",
+                            "postalAddress: Aaccf Amar$00599 First Street$Augusta, MN  30667",
+                            "description: This is the description for Aaccf Amar." );
+                        connection.add( user );
+                    }
+                }
+            }
+        }
+        
+        // Addition of entries during a search should not change anything
+        assertEquals( nbUsers + 1, count );
+        
+        connection.close();
+    }
+}