Blame SOURCES/0077-Ticket-48370-The-eq-index-does-not-get-updated-prope.patch

400eba
From 4a52c95b2f7815c15efd84daf57ced08e7855cc2 Mon Sep 17 00:00:00 2001
400eba
From: Mark Reynolds <mreynolds@redhat.com>
400eba
Date: Mon, 7 Dec 2015 16:45:06 -0500
400eba
Subject: [PATCH 77/78] Ticket 48370 - The 'eq' index does not get updated
400eba
 properly                when deleting and re-adding attributes in            
400eba
    the same modify operation
400eba
400eba
Bug Description:  If you delete several values of the same attribute, and
400eba
                  add at least one of them back in the same operation, the
400eba
                  equality index does not get updated.
400eba
400eba
Fix Description:  Modify the logic of the index code to update the index if
400eba
                  at least one of the values in the entry changes.
400eba
400eba
                  Also did pep8 cleanup of create_test.py
400eba
400eba
https://fedorahosted.org/389/ticket/48370
400eba
400eba
Reviewed by: wibrown(Thanks!)
400eba
400eba
(cherry picked from commit 63b80b5c31ebda51445c662903a28e2a79ebe60a)
400eba
(cherry picked from commit 4a53592ec89d288f182c509dc7fcc104d8cbc4a8)
400eba
---
400eba
 dirsrvtests/create_test.py              | 393 +++++++++++++++++++-------------
400eba
 dirsrvtests/tickets/ticket48370_test.py | 236 +++++++++++++++++++
400eba
 ldap/servers/slapd/back-ldbm/index.c    |  29 +--
400eba
 3 files changed, 480 insertions(+), 178 deletions(-)
400eba
 create mode 100644 dirsrvtests/tickets/ticket48370_test.py
400eba
400eba
diff --git a/dirsrvtests/create_test.py b/dirsrvtests/create_test.py
400eba
index 941e922..5293991 100755
400eba
--- a/dirsrvtests/create_test.py
400eba
+++ b/dirsrvtests/create_test.py
400eba
@@ -22,14 +22,16 @@ import optparse
400eba
 
400eba
 
400eba
 def displayUsage():
400eba
-    print ('\nUsage:\ncreate_ticket.py -t|--ticket <ticket number=""> -s|--suite <suite name=""> ' +
400eba
-           '[ i|--instances <number of="" standalone="" instances=""> [ -m|--masters <number of="" masters=""> ' +
400eba
-           '-h|--hubs <number of="" hubs=""> -c|--consumers <number of="" consumers=""> ] ' +
400eba
-           '-o|--outputfile ]\n')
400eba
-    print ('If only "-t" is provided then a single standalone instance is created.  ' +
400eba
-           'Or you can create a test suite script using "-s|--suite" instead of using "-t|--ticket".' +
400eba
-           'The "-i" option can add mulitple standalone instances(maximum 10).  ' +
400eba
-           'However, you can not mix "-i" with the replication options(-m, -h , -c).  ' +
400eba
+    print ('\nUsage:\ncreate_ticket.py -t|--ticket <ticket number=""> ' +
400eba
+           '-s|--suite <suite name=""> ' +
400eba
+           '[ i|--instances <number of="" standalone="" instances=""> ' +
400eba
+           '[ -m|--masters <number of="" masters=""> -h|--hubs <number of="" hubs=""> ' +
400eba
+           '-c|--consumers <number of="" consumers=""> ] -o|--outputfile ]\n')
400eba
+    print ('If only "-t" is provided then a single standalone instance is ' +
400eba
+           'created.  Or you can create a test suite script using ' +
400eba
+           '"-s|--suite" instead of using "-t|--ticket".  The "-i" option ' +
400eba
+           'can add mulitple standalone instances(maximum 10).  However, you' +
400eba
+           ' can not mix "-i" with the replication options(-m, -h , -c).  ' +
400eba
            'There is a maximum of 10 masters, 10 hubs, and 10 consumers.')
400eba
     exit(1)
400eba
 
400eba
@@ -59,34 +61,47 @@ if len(sys.argv) > 0:
400eba
         displayUsage()
400eba
 
400eba
     if args.ticket and args.suite:
400eba
-        print 'You must choose either "-t|--ticket" or "-s|--suite", but not both.'
400eba
+        print('You must choose either "-t|--ticket" or "-s|--suite", ' +
400eba
+              'but not both.')
400eba
         displayUsage()
400eba
 
400eba
     if int(args.masters) == 0:
400eba
         if int(args.hubs) > 0 or int(args.consumers) > 0:
400eba
-            print 'You must use "-m|--masters" if you want to have hubs and/or consumers'
400eba
+            print('You must use "-m|--masters" if you want to have hubs ' +
400eba
+                  'and/or consumers')
400eba
             displayUsage()
400eba
 
400eba
-    if not args.masters.isdigit() or int(args.masters) > 10 or int(args.masters) < 0:
400eba
-        print 'Invalid value for "--masters", it must be a number and it can not be greater than 10'
400eba
+    if not args.masters.isdigit() or \
400eba
+           int(args.masters) > 10 or \
400eba
+           int(args.masters) < 0:
400eba
+        print('Invalid value for "--masters", it must be a number and it can' +
400eba
+              ' not be greater than 10')
400eba
         displayUsage()
400eba
 
400eba
     if not args.hubs.isdigit() or int(args.hubs) > 10 or int(args.hubs) < 0:
400eba
-        print 'Invalid value for "--hubs", it must be a number and it can not be greater than 10'
400eba
+        print('Invalid value for "--hubs", it must be a number and it can ' +
400eba
+              'not be greater than 10')
400eba
         displayUsage()
400eba
 
400eba
-    if not args.consumers.isdigit() or int(args.consumers) > 10 or int(args.consumers) < 0:
400eba
-        print 'Invalid value for "--consumers", it must be a number and it can not be greater than 10'
400eba
+    if not args.consumers.isdigit() or \
400eba
+           int(args.consumers) > 10 or \
400eba
+           int(args.consumers) < 0:
400eba
+        print('Invalid value for "--consumers", it must be a number and it ' +
400eba
+              'can not be greater than 10')
400eba
         displayUsage()
400eba
 
400eba
     if args.inst:
400eba
-        if not args.inst.isdigit() or int(args.inst) > 10 or int(args.inst) < 1:
400eba
-            print ('Invalid value for "--instances", it must be a number greater than 0 ' +
400eba
-                   'and not greater than 10')
400eba
+        if not args.inst.isdigit() or \
400eba
+               int(args.inst) > 10 or \
400eba
+               int(args.inst) < 1:
400eba
+            print('Invalid value for "--instances", it must be a number ' +
400eba
+                  'greater than 0 and not greater than 10')
400eba
             displayUsage()
400eba
         if int(args.inst) > 0:
400eba
-            if int(args.masters) > 0 or int(args.hubs) > 0 or int(args.consumers) > 0:
400eba
-                print 'You can not mix "--instances" with replication.'
400eba
+            if int(args.masters) > 0 or \
400eba
+               int(args.hubs) > 0 or \
400eba
+               int(args.consumers) > 0:
400eba
+                print('You can not mix "--instances" with replication.')
400eba
                 displayUsage()
400eba
 
400eba
     # Extract usable values
400eba
@@ -120,9 +135,11 @@ if len(sys.argv) > 0:
400eba
     #
400eba
     # Write the imports
400eba
     #
400eba
-    TEST.write('import os\nimport sys\nimport time\nimport ldap\nimport logging\nimport pytest\n')
400eba
-    TEST.write('from lib389 import DirSrv, Entry, tools, tasks\nfrom lib389.tools import DirSrvTools\n' +
400eba
-               'from lib389._constants import *\nfrom lib389.properties import *\n' +
400eba
+    TEST.write('import os\nimport sys\nimport time\nimport ldap\n' +
400eba
+               'import logging\nimport pytest\n')
400eba
+    TEST.write('from lib389 import DirSrv, Entry, tools, tasks\nfrom ' +
400eba
+               'lib389.tools import DirSrvTools\nfrom lib389._constants ' +
400eba
+               'import *\nfrom lib389.properties import *\n' +
400eba
                'from lib389.tasks import *\nfrom lib389.utils import *\n\n')
400eba
 
400eba
     #
400eba
@@ -154,13 +171,16 @@ if len(sys.argv) > 0:
400eba
 
400eba
         for idx in range(masters):
400eba
             TEST.write('        master' + str(idx + 1) + '.open()\n')
400eba
-            TEST.write('        self.master' + str(idx + 1) + ' = master' + str(idx + 1) + '\n')
400eba
+            TEST.write('        self.master' + str(idx + 1) + ' = master' +
400eba
+                       str(idx + 1) + '\n')
400eba
         for idx in range(hubs):
400eba
             TEST.write('        hub' + str(idx + 1) + '.open()\n')
400eba
-            TEST.write('        self.hub' + str(idx + 1) + ' = hub' + str(idx + 1) + '\n')
400eba
+            TEST.write('        self.hub' + str(idx + 1) + ' = hub' +
400eba
+                       str(idx + 1) + '\n')
400eba
         for idx in range(consumers):
400eba
             TEST.write('        consumer' + str(idx + 1) + '.open()\n')
400eba
-            TEST.write('        self.consumer' + str(idx + 1) + ' = consumer' + str(idx + 1) + '\n')
400eba
+            TEST.write('        self.consumer' + str(idx + 1) + ' = consumer' +
400eba
+                       str(idx + 1) + '\n')
400eba
         TEST.write('\n\n')
400eba
     else:
400eba
         #
400eba
@@ -184,7 +204,8 @@ if len(sys.argv) > 0:
400eba
             else:
400eba
                 idx = str(idx)
400eba
             TEST.write('        standalone' + idx + '.open()\n')
400eba
-            TEST.write('        self.standalone' + idx + ' = standalone' + idx + '\n')
400eba
+            TEST.write('        self.standalone' + idx + ' = standalone' +
400eba
+                       idx + '\n')
400eba
         TEST.write('\n\n')
400eba
 
400eba
     #
400eba
@@ -194,7 +215,8 @@ if len(sys.argv) > 0:
400eba
     TEST.write('def topology(request):\n')
400eba
     TEST.write('    global installation1_prefix\n')
400eba
     TEST.write('    if installation1_prefix:\n')
400eba
-    TEST.write('        args_instance[SER_DEPLOYED_DIR] = installation1_prefix\n\n')
400eba
+    TEST.write('        args_instance[SER_DEPLOYED_DIR] = ' +
400eba
+               'installation1_prefix\n\n')
400eba
 
400eba
     if repl_deployment:
400eba
         #
400eba
@@ -204,20 +226,25 @@ if len(sys.argv) > 0:
400eba
             idx = str(idx + 1)
400eba
             TEST.write('    # Creating master ' + idx + '...\n')
400eba
             TEST.write('    master' + idx + ' = DirSrv(verbose=False)\n')
400eba
-            TEST.write('    args_instance[SER_HOST] = HOST_MASTER_' + idx + '\n')
400eba
-            TEST.write('    args_instance[SER_PORT] = PORT_MASTER_' + idx + '\n')
400eba
-            TEST.write('    args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_' + idx + '\n')
400eba
-            TEST.write('    args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX\n')
400eba
+            TEST.write('    args_instance[SER_HOST] = HOST_MASTER_' + idx +
400eba
+                       '\n')
400eba
+            TEST.write('    args_instance[SER_PORT] = PORT_MASTER_' + idx +
400eba
+                       '\n')
400eba
+            TEST.write('    args_instance[SER_SERVERID_PROP] = ' +
400eba
+                       'SERVERID_MASTER_' + idx + '\n')
400eba
+            TEST.write('    args_instance[SER_CREATION_SUFFIX] = ' +
400eba
+                       'DEFAULT_SUFFIX\n')
400eba
             TEST.write('    args_master = args_instance.copy()\n')
400eba
             TEST.write('    master' + idx + '.allocate(args_master)\n')
400eba
-            TEST.write('    instance_master' + idx + ' = master' + idx + '.exists()\n')
400eba
+            TEST.write('    instance_master' + idx + ' = master' + idx +
400eba
+                       '.exists()\n')
400eba
             TEST.write('    if instance_master' + idx + ':\n')
400eba
             TEST.write('        master' + idx + '.delete()\n')
400eba
             TEST.write('    master' + idx + '.create()\n')
400eba
             TEST.write('    master' + idx + '.open()\n')
400eba
-            TEST.write('    master' + idx + '.replica.enableReplication(suffix=SUFFIX, ' +
400eba
-                                            'role=REPLICAROLE_MASTER, ' +
400eba
-                                            'replicaId=REPLICAID_MASTER_' + idx + ')\n\n')
400eba
+            TEST.write('    master' + idx + '.replica.enableReplication' +
400eba
+                       '(suffix=SUFFIX, role=REPLICAROLE_MASTER, ' +
400eba
+                       'replicaId=REPLICAID_MASTER_' + idx + ')\n\n')
400eba
 
400eba
         for idx in range(hubs):
400eba
             idx = str(idx + 1)
400eba
@@ -225,37 +252,45 @@ if len(sys.argv) > 0:
400eba
             TEST.write('    hub' + idx + ' = DirSrv(verbose=False)\n')
400eba
             TEST.write('    args_instance[SER_HOST] = HOST_HUB_' + idx + '\n')
400eba
             TEST.write('    args_instance[SER_PORT] = PORT_HUB_' + idx + '\n')
400eba
-            TEST.write('    args_instance[SER_SERVERID_PROP] = SERVERID_HUB_' + idx + '\n')
400eba
-            TEST.write('    args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX\n')
400eba
+            TEST.write('    args_instance[SER_SERVERID_PROP] = SERVERID_HUB_' +
400eba
+                       idx + '\n')
400eba
+            TEST.write('    args_instance[SER_CREATION_SUFFIX] = ' +
400eba
+                       'DEFAULT_SUFFIX\n')
400eba
             TEST.write('    args_hub = args_instance.copy()\n')
400eba
             TEST.write('    hub' + idx + '.allocate(args_hub)\n')
400eba
-            TEST.write('    instance_hub' + idx + ' = hub' + idx + '.exists()\n')
400eba
+            TEST.write('    instance_hub' + idx + ' = hub' + idx +
400eba
+                       '.exists()\n')
400eba
             TEST.write('    if instance_hub' + idx + ':\n')
400eba
             TEST.write('        hub' + idx + '.delete()\n')
400eba
             TEST.write('    hub' + idx + '.create()\n')
400eba
             TEST.write('    hub' + idx + '.open()\n')
400eba
-            TEST.write('    hub' + idx + '.replica.enableReplication(suffix=SUFFIX, ' +
400eba
-                                            'role=REPLICAROLE_HUB, ' +
400eba
-                                            'replicaId=REPLICAID_HUB_' + idx + ')\n\n')
400eba
+            TEST.write('    hub' + idx + '.replica.enableReplication' +
400eba
+                       '(suffix=SUFFIX, role=REPLICAROLE_HUB, ' +
400eba
+                       'replicaId=REPLICAID_HUB_' + idx + ')\n\n')
400eba
 
400eba
         for idx in range(consumers):
400eba
             idx = str(idx + 1)
400eba
             TEST.write('    # Creating consumer ' + idx + '...\n')
400eba
             TEST.write('    consumer' + idx + ' = DirSrv(verbose=False)\n')
400eba
-            TEST.write('    args_instance[SER_HOST] = HOST_CONSUMER_' + idx + '\n')
400eba
-            TEST.write('    args_instance[SER_PORT] = PORT_CONSUMER_' + idx + '\n')
400eba
-            TEST.write('    args_instance[SER_SERVERID_PROP] = SERVERID_CONSUMER_' + idx + '\n')
400eba
-            TEST.write('    args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX\n')
400eba
+            TEST.write('    args_instance[SER_HOST] = HOST_CONSUMER_' + idx +
400eba
+                       '\n')
400eba
+            TEST.write('    args_instance[SER_PORT] = PORT_CONSUMER_' + idx +
400eba
+                       '\n')
400eba
+            TEST.write('    args_instance[SER_SERVERID_PROP] = ' +
400eba
+                       'SERVERID_CONSUMER_' + idx + '\n')
400eba
+            TEST.write('    args_instance[SER_CREATION_SUFFIX] = ' +
400eba
+                       'DEFAULT_SUFFIX\n')
400eba
             TEST.write('    args_consumer = args_instance.copy()\n')
400eba
             TEST.write('    consumer' + idx + '.allocate(args_consumer)\n')
400eba
-            TEST.write('    instance_consumer' + idx + ' = consumer' + idx + '.exists()\n')
400eba
+            TEST.write('    instance_consumer' + idx + ' = consumer' + idx +
400eba
+                       '.exists()\n')
400eba
             TEST.write('    if instance_consumer' + idx + ':\n')
400eba
             TEST.write('        consumer' + idx + '.delete()\n')
400eba
             TEST.write('    consumer' + idx + '.create()\n')
400eba
             TEST.write('    consumer' + idx + '.open()\n')
400eba
-            TEST.write('    consumer' + idx + '.replica.enableReplication(suffix=SUFFIX, ' +
400eba
-                                            'role=REPLICAROLE_CONSUMER, ' +
400eba
-                                            'replicaId=CONSUMER_REPLICAID)\n\n')
400eba
+            TEST.write('    consumer' + idx + '.replica.enableReplication' +
400eba
+                       '(suffix=SUFFIX, role=REPLICAROLE_CONSUMER, ' +
400eba
+                       'replicaId=CONSUMER_REPLICAID)\n\n')
400eba
 
400eba
         #
400eba
         # Create the master agreements
400eba
@@ -274,39 +309,61 @@ if len(sys.argv) > 0:
400eba
                 if master_idx == idx:
400eba
                     # skip ourselves
400eba
                     continue
400eba
-                TEST.write('    # Creating agreement from master ' + str(master_idx) + ' to master ' + str(idx) + '\n')
400eba
-                TEST.write("    properties = {RA_NAME:      r'meTo_$host:$port',\n")
400eba
-                TEST.write("                  RA_BINDDN:    defaultProperties[REPLICATION_BIND_DN],\n")
400eba
-                TEST.write("                  RA_BINDPW:    defaultProperties[REPLICATION_BIND_PW],\n")
400eba
-                TEST.write("                  RA_METHOD:    defaultProperties[REPLICATION_BIND_METHOD],\n")
400eba
-                TEST.write("                  RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}\n")
400eba
-                TEST.write('    m' + str(master_idx) + '_m' + str(idx) + '_agmt = master' + str(master_idx) +
400eba
+                TEST.write('    # Creating agreement from master ' +
400eba
+                           str(master_idx) + ' to master ' + str(idx) + '\n')
400eba
+                TEST.write("    properties = {RA_NAME:      " +
400eba
+                           "r'meTo_$host:$port',\n")
400eba
+                TEST.write("                  RA_BINDDN:    " +
400eba
+                           "defaultProperties[REPLICATION_BIND_DN],\n")
400eba
+                TEST.write("                  RA_BINDPW:    " +
400eba
+                           "defaultProperties[REPLICATION_BIND_PW],\n")
400eba
+                TEST.write("                  RA_METHOD:    " +
400eba
+                           "defaultProperties[REPLICATION_BIND_METHOD],\n")
400eba
+                TEST.write("                  RA_TRANSPORT_PROT: " +
400eba
+                           "defaultProperties[REPLICATION_TRANSPORT]}\n")
400eba
+                TEST.write('    m' + str(master_idx) + '_m' + str(idx) +
400eba
+                           '_agmt = master' + str(master_idx) +
400eba
                             '.agreement.create(suffix=SUFFIX, host=master' +
400eba
-                            str(idx) + '.host, port=master' + str(idx) + '.port, properties=properties)\n')
400eba
-                TEST.write('    if not m' + str(master_idx) + '_m' + str(idx) + '_agmt:\n')
400eba
-                TEST.write('        log.fatal("Fail to create a master -> master replica agreement")\n')
400eba
+                            str(idx) + '.host, port=master' + str(idx) +
400eba
+                            '.port, properties=properties)\n')
400eba
+                TEST.write('    if not m' + str(master_idx) + '_m' + str(idx) +
400eba
+                           '_agmt:\n')
400eba
+                TEST.write('        log.fatal("Fail to create a master -> ' +
400eba
+                           'master replica agreement")\n')
400eba
                 TEST.write('        sys.exit(1)\n')
400eba
-                TEST.write('    log.debug("%s created" % m' + str(master_idx) + '_m' + str(idx) + '_agmt)\n\n')
400eba
+                TEST.write('    log.debug("%s created" % m' + str(master_idx) +
400eba
+                           '_m' + str(idx) + '_agmt)\n\n')
400eba
                 agmt_count += 1
400eba
 
400eba
             for idx in range(hubs):
400eba
                 idx += 1
400eba
                 #
400eba
-                # Create agreements from each master to each hub (master -> hub)
400eba
+                # Create agmts from each master to each hub (master -> hub)
400eba
                 #
400eba
-                TEST.write('    # Creating agreement from master ' + str(master_idx) + ' to hub ' + str(idx) + '\n')
400eba
-                TEST.write("    properties = {RA_NAME:      r'meTo_$host:$port',\n")
400eba
-                TEST.write("                  RA_BINDDN:    defaultProperties[REPLICATION_BIND_DN],\n")
400eba
-                TEST.write("                  RA_BINDPW:    defaultProperties[REPLICATION_BIND_PW],\n")
400eba
-                TEST.write("                  RA_METHOD:    defaultProperties[REPLICATION_BIND_METHOD],\n")
400eba
-                TEST.write("                  RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}\n")
400eba
-                TEST.write('    m' + str(master_idx) + '_h' + str(idx) + '_agmt = master' + str(master_idx) +
400eba
-                            '.agreement.create(suffix=SUFFIX, host=hub' +
400eba
-                            str(idx) + '.host, port=hub' + str(idx) + '.port, properties=properties)\n')
400eba
-                TEST.write('    if not m' + str(master_idx) + '_h' + str(idx) + '_agmt:\n')
400eba
-                TEST.write('        log.fatal("Fail to create a master -> hub replica agreement")\n')
400eba
+                TEST.write('    # Creating agreement from master ' +
400eba
+                           str(master_idx) + ' to hub ' + str(idx) + '\n')
400eba
+                TEST.write("    properties = {RA_NAME:      " +
400eba
+                           "r'meTo_$host:$port',\n")
400eba
+                TEST.write("                  RA_BINDDN:    " +
400eba
+                           "defaultProperties[REPLICATION_BIND_DN],\n")
400eba
+                TEST.write("                  RA_BINDPW:    " +
400eba
+                           "defaultProperties[REPLICATION_BIND_PW],\n")
400eba
+                TEST.write("                  RA_METHOD:    " +
400eba
+                           "defaultProperties[REPLICATION_BIND_METHOD],\n")
400eba
+                TEST.write("                  RA_TRANSPORT_PROT: " +
400eba
+                           "defaultProperties[REPLICATION_TRANSPORT]}\n")
400eba
+                TEST.write('    m' + str(master_idx) + '_h' + str(idx) +
400eba
+                           '_agmt = master' + str(master_idx) +
400eba
+                           '.agreement.create(suffix=SUFFIX, host=hub' +
400eba
+                           str(idx) + '.host, port=hub' + str(idx) +
400eba
+                           '.port, properties=properties)\n')
400eba
+                TEST.write('    if not m' + str(master_idx) + '_h' + str(idx) +
400eba
+                           '_agmt:\n')
400eba
+                TEST.write('        log.fatal("Fail to create a master -> ' +
400eba
+                           'hub replica agreement")\n')
400eba
                 TEST.write('        sys.exit(1)\n')
400eba
-                TEST.write('    log.debug("%s created" % m' + str(master_idx) + '_h' + str(idx) + '_agmt)\n\n')
400eba
+                TEST.write('    log.debug("%s created" % m' + str(master_idx) +
400eba
+                           '_h' + str(idx) + '_agmt)\n\n')
400eba
                 agmt_count += 1
400eba
 
400eba
         #
400eba
@@ -322,24 +379,35 @@ if len(sys.argv) > 0:
400eba
                 #
400eba
                 # Create agreements from each hub to each consumer
400eba
                 #
400eba
-                TEST.write('    # Creating agreement from hub ' + str(hub_idx) + ' to consumer ' + str(idx) + '\n')
400eba
-                TEST.write("    properties = {RA_NAME:      r'meTo_$host:$port',\n")
400eba
-                TEST.write("                  RA_BINDDN:    defaultProperties[REPLICATION_BIND_DN],\n")
400eba
-                TEST.write("                  RA_BINDPW:    defaultProperties[REPLICATION_BIND_PW],\n")
400eba
-                TEST.write("                  RA_METHOD:    defaultProperties[REPLICATION_BIND_METHOD],\n")
400eba
-                TEST.write("                  RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}\n")
400eba
-                TEST.write('    h' + str(hub_idx) + '_c' + str(idx) + '_agmt = hub' +
400eba
-                            str(hub_idx) + '.agreement.create(suffix=SUFFIX, host=consumer' +
400eba
-                            str(idx) + '.host, port=consumer' + str(idx) + '.port, properties=properties)\n')
400eba
-                TEST.write('    if not h' + str(hub_idx) + '_c' + str(idx) + '_agmt:\n')
400eba
-                TEST.write('        log.fatal("Fail to create a hub -> consumer replica agreement")\n')
400eba
+                TEST.write('    # Creating agreement from hub ' + str(hub_idx)
400eba
+                           + ' to consumer ' + str(idx) + '\n')
400eba
+                TEST.write("    properties = {RA_NAME:      " +
400eba
+                           "r'meTo_$host:$port',\n")
400eba
+                TEST.write("                  RA_BINDDN:    " +
400eba
+                           "defaultProperties[REPLICATION_BIND_DN],\n")
400eba
+                TEST.write("                  RA_BINDPW:    " +
400eba
+                           "defaultProperties[REPLICATION_BIND_PW],\n")
400eba
+                TEST.write("                  RA_METHOD:    " +
400eba
+                           "defaultProperties[REPLICATION_BIND_METHOD],\n")
400eba
+                TEST.write("                  RA_TRANSPORT_PROT: " +
400eba
+                           "defaultProperties[REPLICATION_TRANSPORT]}\n")
400eba
+                TEST.write('    h' + str(hub_idx) + '_c' + str(idx) +
400eba
+                           '_agmt = hub' + str(hub_idx) +
400eba
+                           '.agreement.create(suffix=SUFFIX, host=consumer' +
400eba
+                           str(idx) + '.host, port=consumer' + str(idx) +
400eba
+                           '.port, properties=properties)\n')
400eba
+                TEST.write('    if not h' + str(hub_idx) + '_c' + str(idx) +
400eba
+                           '_agmt:\n')
400eba
+                TEST.write('        log.fatal("Fail to create a hub -> ' +
400eba
+                           'consumer replica agreement")\n')
400eba
                 TEST.write('        sys.exit(1)\n')
400eba
-                TEST.write('    log.debug("%s created" % h' + str(hub_idx) + '_c' + str(idx) + '_agmt)\n\n')
400eba
+                TEST.write('    log.debug("%s created" % h' + str(hub_idx) +
400eba
+                           '_c' + str(idx) + '_agmt)\n\n')
400eba
                 agmt_count += 1
400eba
 
400eba
         if hubs == 0:
400eba
             #
400eba
-            # No Hubs, see if there are any consumers to create agreements to...
400eba
+            # No Hubs, see if there are any consumers to create agreements to
400eba
             #
400eba
             for idx in range(masters):
400eba
                 master_idx = idx + 1
400eba
@@ -351,27 +419,40 @@ if len(sys.argv) > 0:
400eba
                     #
400eba
                     # Create agreements from each master to each consumer
400eba
                     #
400eba
-                    TEST.write('    # Creating agreement from master ' + str(master_idx) +
400eba
-                               ' to consumer ' + str(idx) + '\n')
400eba
-                    TEST.write("    properties = {RA_NAME:      r'meTo_$host:$port',\n")
400eba
-                    TEST.write("                  RA_BINDDN:    defaultProperties[REPLICATION_BIND_DN],\n")
400eba
-                    TEST.write("                  RA_BINDPW:    defaultProperties[REPLICATION_BIND_PW],\n")
400eba
-                    TEST.write("                  RA_METHOD:    defaultProperties[REPLICATION_BIND_METHOD],\n")
400eba
-                    TEST.write("                  RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}\n")
400eba
-                    TEST.write('    m' + str(master_idx) + '_c' + str(idx) + '_agmt = master' + str(master_idx) +
400eba
-                                '.agreement.create(suffix=SUFFIX, host=consumer' +
400eba
-                                str(idx) + '.host, port=consumer' + str(idx) +
400eba
-                                '.port, properties=properties)\n')
400eba
-                    TEST.write('    if not m' + str(master_idx) + '_c' + str(idx) + '_agmt:\n')
400eba
-                    TEST.write('        log.fatal("Fail to create a hub -> consumer replica agreement")\n')
400eba
+                    TEST.write('    # Creating agreement from master ' +
400eba
+                               str(master_idx) + ' to consumer ' + str(idx) +
400eba
+                               '\n')
400eba
+                    TEST.write("    properties = {RA_NAME:      " +
400eba
+                               "r'meTo_$host:$port',\n")
400eba
+                    TEST.write("                  RA_BINDDN:    " +
400eba
+                               "defaultProperties[REPLICATION_BIND_DN],\n")
400eba
+                    TEST.write("                  RA_BINDPW:    " +
400eba
+                               "defaultProperties[REPLICATION_BIND_PW],\n")
400eba
+                    TEST.write("                  RA_METHOD:    " +
400eba
+                               "defaultProperties[REPLICATION_BIND_METHOD],\n")
400eba
+                    TEST.write("                  RA_TRANSPORT_PROT: " +
400eba
+                               "defaultProperties[REPLICATION_TRANSPORT]}\n")
400eba
+                    TEST.write('    m' + str(master_idx) + '_c' + str(idx) +
400eba
+                               '_agmt = master' + str(master_idx) +
400eba
+                               '.agreement.create(suffix=SUFFIX, ' +
400eba
+                               'host=consumer' + str(idx) +
400eba
+                               '.host, port=consumer' + str(idx) +
400eba
+                               '.port, properties=properties)\n')
400eba
+                    TEST.write('    if not m' + str(master_idx) + '_c' +
400eba
+                               str(idx) + '_agmt:\n')
400eba
+                    TEST.write('        log.fatal("Fail to create a hub -> ' +
400eba
+                               'consumer replica agreement")\n')
400eba
                     TEST.write('        sys.exit(1)\n')
400eba
-                    TEST.write('    log.debug("%s created" % m' + str(master_idx) + '_c' + str(idx) + '_agmt)\n\n')
400eba
+                    TEST.write('    log.debug("%s created" % m' +
400eba
+                               str(master_idx) + '_c' + str(idx) +
400eba
+                               '_agmt)\n\n')
400eba
                     agmt_count += 1
400eba
 
400eba
         #
400eba
         # Add sleep that allows all the agreemnts to get situated
400eba
         #
400eba
-        TEST.write('    # Allow the replicas to get situated with the new agreements...\n')
400eba
+        TEST.write('    # Allow the replicas to get situated with the new ' +
400eba
+                   'agreements...\n')
400eba
         TEST.write('    time.sleep(5)\n\n')
400eba
 
400eba
         #
400eba
@@ -388,7 +469,8 @@ if len(sys.argv) > 0:
400eba
                 continue
400eba
             TEST.write('    master1.agreement.init(SUFFIX, HOST_MASTER_' +
400eba
                        str(idx) + ', PORT_MASTER_' + str(idx) + ')\n')
400eba
-            TEST.write('    master1.waitForReplInit(m1_m' + str(idx) + '_agmt)\n')
400eba
+            TEST.write('    master1.waitForReplInit(m1_m' + str(idx) +
400eba
+                       '_agmt)\n')
400eba
 
400eba
         # Hubs
400eba
         consumers_inited = False
400eba
@@ -396,23 +478,27 @@ if len(sys.argv) > 0:
400eba
             idx += 1
400eba
             TEST.write('    master1.agreement.init(SUFFIX, HOST_HUB_' +
400eba
                    str(idx) + ', PORT_HUB_' + str(idx) + ')\n')
400eba
-            TEST.write('    master1.waitForReplInit(m1_h' + str(idx) + '_agmt)\n')
400eba
+            TEST.write('    master1.waitForReplInit(m1_h' + str(idx) +
400eba
+                       '_agmt)\n')
400eba
             for idx in range(consumers):
400eba
                 if consumers_inited:
400eba
                     continue
400eba
                 idx += 1
400eba
                 TEST.write('    hub1.agreement.init(SUFFIX, HOST_CONSUMER_' +
400eba
                            str(idx) + ', PORT_CONSUMER_' + str(idx) + ')\n')
400eba
-                TEST.write('    hub1.waitForReplInit(h1_c' + str(idx) + '_agmt)\n')
400eba
+                TEST.write('    hub1.waitForReplInit(h1_c' + str(idx) +
400eba
+                           '_agmt)\n')
400eba
             consumers_inited = True
400eba
 
400eba
         # Consumers (master -> consumer)
400eba
         if hubs == 0:
400eba
             for idx in range(consumers):
400eba
                 idx += 1
400eba
-                TEST.write('    master1.agreement.init(SUFFIX, HOST_CONSUMER_' +
400eba
-                           str(idx) + ', PORT_CONSUMER_' + str(idx) + ')\n')
400eba
-                TEST.write('    master1.waitForReplInit(m1_c' + str(idx) + '_agmt)\n')
400eba
+                TEST.write('    master1.agreement.init(SUFFIX, ' +
400eba
+                           'HOST_CONSUMER_' + str(idx) + ', PORT_CONSUMER_' +
400eba
+                           str(idx) + ')\n')
400eba
+                TEST.write('    master1.waitForReplInit(m1_c' + str(idx) +
400eba
+                           '_agmt)\n')
400eba
 
400eba
         TEST.write('\n')
400eba
 
400eba
@@ -420,7 +506,7 @@ if len(sys.argv) > 0:
400eba
         # Write replicaton check
400eba
         #
400eba
         if agmt_count > 0:
400eba
-            # Find the lowest replica type in the deployment(consumer -> master)
400eba
+            # Find the lowest replica type (consumer -> master)
400eba
             if consumers > 0:
400eba
                 replica = 'consumer1'
400eba
             elif hubs > 0:
400eba
@@ -428,7 +514,8 @@ if len(sys.argv) > 0:
400eba
             else:
400eba
                 replica = 'master2'
400eba
             TEST.write('    # Check replication is working...\n')
400eba
-            TEST.write('    if master1.testReplication(DEFAULT_SUFFIX, ' + replica + '):\n')
400eba
+            TEST.write('    if master1.testReplication(DEFAULT_SUFFIX, ' +
400eba
+                       replica + '):\n')
400eba
             TEST.write("        log.info('Replication is working.')\n")
400eba
             TEST.write('    else:\n')
400eba
             TEST.write("        log.fatal('Replication is not working.')\n")
400eba
@@ -465,15 +552,22 @@ if len(sys.argv) > 0:
400eba
                 idx = str(idx)
400eba
             TEST.write('    # Creating standalone instance ' + idx + '...\n')
400eba
             TEST.write('    standalone' + idx + ' = DirSrv(verbose=False)\n')
400eba
-            TEST.write('    args_instance[SER_HOST] = HOST_STANDALONE' + idx + '\n')
400eba
-            TEST.write('    args_instance[SER_PORT] = PORT_STANDALONE' + idx + '\n')
400eba
-            TEST.write('    args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE' + idx + '\n')
400eba
-            TEST.write('    args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX\n')
400eba
-            TEST.write('    args_standalone' + idx + ' = args_instance.copy()\n')
400eba
-            TEST.write('    standalone' + idx + '.allocate(args_standalone' + idx + ')\n')
400eba
+            TEST.write('    args_instance[SER_HOST] = HOST_STANDALONE' +
400eba
+                       idx + '\n')
400eba
+            TEST.write('    args_instance[SER_PORT] = PORT_STANDALONE' +
400eba
+                       idx + '\n')
400eba
+            TEST.write('    args_instance[SER_SERVERID_PROP] = ' +
400eba
+                       'SERVERID_STANDALONE' + idx + '\n')
400eba
+            TEST.write('    args_instance[SER_CREATION_SUFFIX] = ' +
400eba
+                       'DEFAULT_SUFFIX\n')
400eba
+            TEST.write('    args_standalone' + idx + ' = args_instance.copy' +
400eba
+                       '()\n')
400eba
+            TEST.write('    standalone' + idx + '.allocate(args_standalone' +
400eba
+                       idx + ')\n')
400eba
 
400eba
             # Get the status of the instance and restart it if it exists
400eba
-            TEST.write('    instance_standalone' + idx + ' = standalone' + idx + '.exists()\n')
400eba
+            TEST.write('    instance_standalone' + idx + ' = standalone' +
400eba
+                       idx + '.exists()\n')
400eba
 
400eba
             # Remove the instance
400eba
             TEST.write('    if instance_standalone' + idx + ':\n')
400eba
@@ -503,12 +597,20 @@ if len(sys.argv) > 0:
400eba
         TEST.write('def test_ticket' + ticket + '(topology):\n')
400eba
         TEST.write("    '''\n")
400eba
         if repl_deployment:
400eba
-            TEST.write('    Write your replication testcase here.\n\n')
400eba
-            TEST.write('    To access each DirSrv instance use:  topology.master1, topology.master2,\n' +
400eba
-                       '        ..., topology.hub1, ..., topology.consumer1, ...\n')
400eba
+            TEST.write('    """Write your replication testcase here.\n\n')
400eba
+            TEST.write('    To access each DirSrv instance use:  ' +
400eba
+                       'topology.master1, topology.master2,\n' +
400eba
+                       '        ..., topology.hub1, ..., topology.consumer1' +
400eba
+                       ',...\n\n')
400eba
+            TEST.write('    Also, if you need any testcase initialization,\n')
400eba
+            TEST.write('    please, write additional fixture for that' +
400eba
+                       '(include ' + 'finalizer).\n')
400eba
         else:
400eba
-            TEST.write('    Write your testcase here...\n')
400eba
-        TEST.write("    '''\n\n")
400eba
+            TEST.write('    """Write your testcase here...\n\n')
400eba
+            TEST.write('    Also, if you need any testcase initialization,\n')
400eba
+            TEST.write('    please, write additional fixture for that' +
400eba
+                       '(include finalizer).\n')
400eba
+        TEST.write('    """\n\n')
400eba
         TEST.write("    log.info('Test complete')\n")
400eba
         TEST.write("\n\n")
400eba
     else:
400eba
@@ -520,43 +622,11 @@ if len(sys.argv) > 0:
400eba
 
400eba
         # Write the first initial empty test function
400eba
         TEST.write('def test_' + suite + '_#####(topology):\n')
400eba
-        TEST.write("    '''\n")
400eba
-        TEST.write('    Write a single test here...\n')
400eba
-        TEST.write("    '''\n\n    return\n\n\n")
400eba
-
400eba
-    #
400eba
-    # Write the final function here - delete each instance
400eba
-    #
400eba
-    if ticket:
400eba
-        TEST.write('def test_ticket' + ticket + '_final(topology):\n')
400eba
-    else:
400eba
-        # suite
400eba
-        TEST.write('def test_' + suite + '_final(topology):\n')
400eba
-    if repl_deployment:
400eba
-        for idx in range(masters):
400eba
-            idx += 1
400eba
-            TEST.write('    topology.master' + str(idx) + '.delete()\n')
400eba
-        for idx in range(hubs):
400eba
-            idx += 1
400eba
-            TEST.write('    topology.hub' + str(idx) + '.delete()\n')
400eba
-        for idx in range(consumers):
400eba
-            idx += 1
400eba
-            TEST.write('    topology.consumer' + str(idx) + '.delete()\n')
400eba
-    else:
400eba
-        for idx in range(instances):
400eba
-            idx += 1
400eba
-            if idx == 1:
400eba
-                idx = ''
400eba
-            else:
400eba
-                idx = str(idx)
400eba
-            TEST.write('    topology.standalone' + idx + '.delete()\n')
400eba
-
400eba
-    if ticket:
400eba
-        TEST.write("    log.info('Testcase PASSED')\n")
400eba
-    else:
400eba
-        # suite
400eba
-        TEST.write("    log.info('" + suite + " test suite PASSED')\n")
400eba
-    TEST.write('\n\n')
400eba
+        TEST.write('    """Write a single test here...\n\n')
400eba
+        TEST.write('    Also, if you need any test suite initialization,\n')
400eba
+        TEST.write('    please, write additional fixture for that(include ' +
400eba
+                   'finalizer).\n')
400eba
+        TEST.write('    """\n\n    return\n\n\n')
400eba
 
400eba
     #
400eba
     # Write the main function
400eba
@@ -576,7 +646,10 @@ if len(sys.argv) > 0:
400eba
     TEST.write('\n\n')
400eba
 
400eba
     TEST.write("if __name__ == '__main__':\n")
400eba
-    TEST.write('    run_isolated()\n\n')
400eba
+    TEST.write('    # Run isolated\n')
400eba
+    TEST.write('    # -s for DEBUG mode\n')
400eba
+    TEST.write('    CURRENT_FILE = os.path.realpath(__file__)\n')
400eba
+    TEST.write('    pytest.main("-s %s" % CURRENT_FILE)\n')
400eba
 
400eba
     #
400eba
     # Done, close things up
400eba
diff --git a/dirsrvtests/tickets/ticket48370_test.py b/dirsrvtests/tickets/ticket48370_test.py
400eba
new file mode 100644
400eba
index 0000000..f5b1f47
400eba
--- /dev/null
400eba
+++ b/dirsrvtests/tickets/ticket48370_test.py
400eba
@@ -0,0 +1,236 @@
400eba
+import os
400eba
+import ldap
400eba
+import logging
400eba
+import pytest
400eba
+from lib389 import DirSrv, Entry
400eba
+from lib389._constants import *
400eba
+from lib389.properties import *
400eba
+from lib389.tasks import *
400eba
+from lib389.utils import *
400eba
+
400eba
+logging.getLogger(__name__).setLevel(logging.DEBUG)
400eba
+log = logging.getLogger(__name__)
400eba
+
400eba
+installation1_prefix = None
400eba
+
400eba
+
400eba
+class TopologyStandalone(object):
400eba
+    def __init__(self, standalone):
400eba
+        standalone.open()
400eba
+        self.standalone = standalone
400eba
+
400eba
+
400eba
+@pytest.fixture(scope="module")
400eba
+def topology(request):
400eba
+    global installation1_prefix
400eba
+    if installation1_prefix:
400eba
+        args_instance[SER_DEPLOYED_DIR] = installation1_prefix
400eba
+
400eba
+    # Creating standalone instance ...
400eba
+    standalone = DirSrv(verbose=False)
400eba
+    args_instance[SER_HOST] = HOST_STANDALONE
400eba
+    args_instance[SER_PORT] = PORT_STANDALONE
400eba
+    args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
400eba
+    args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
400eba
+    args_standalone = args_instance.copy()
400eba
+    standalone.allocate(args_standalone)
400eba
+    instance_standalone = standalone.exists()
400eba
+    if instance_standalone:
400eba
+        standalone.delete()
400eba
+    standalone.create()
400eba
+    standalone.open()
400eba
+
400eba
+    # Delete each instance in the end
400eba
+    def fin():
400eba
+        standalone.delete()
400eba
+    request.addfinalizer(fin)
400eba
+
400eba
+    # Clear out the tmp dir
400eba
+    standalone.clearTmpDir(__file__)
400eba
+
400eba
+    return TopologyStandalone(standalone)
400eba
+
400eba
+
400eba
+def test_ticket48370(topology):
400eba
+    """
400eba
+    Deleting attirbute values and readding a value does not properly update
400eba
+    the pres index.  The values are not actually deleted from the index
400eba
+    """
400eba
+
400eba
+    DN = 'uid=user0099,' + DEFAULT_SUFFIX
400eba
+
400eba
+    #
400eba
+    # Add an entry
400eba
+    #
400eba
+    topology.standalone.add_s(Entry((DN, {
400eba
+                              'objectclass': ['top', 'person',
400eba
+                                              'organizationalPerson',
400eba
+                                              'inetorgperson',
400eba
+                                              'posixAccount'],
400eba
+                              'givenname': 'test',
400eba
+                              'sn': 'user',
400eba
+                              'loginshell': '/bin/bash',
400eba
+                              'uidNumber': '10099',
400eba
+                              'gidNumber': '10099',
400eba
+                              'gecos': 'Test User',
400eba
+                              'mail': ['user0099@dev.null',
400eba
+                                       'alias@dev.null',
400eba
+                                       'user0099@redhat.com'],
400eba
+                              'cn': 'Test User',
400eba
+                              'homeDirectory': '/home/user0099',
400eba
+                              'uid': 'admin2',
400eba
+                              'userpassword': 'password'})))
400eba
+
400eba
+    #
400eba
+    # Perform modify (delete & add mail attributes)
400eba
+    #
400eba
+    try:
400eba
+        topology.standalone.modify_s(DN, [(ldap.MOD_DELETE,
400eba
+                                           'mail',
400eba
+                                           'user0099@dev.null'),
400eba
+                                          (ldap.MOD_DELETE,
400eba
+                                           'mail',
400eba
+                                           'alias@dev.null'),
400eba
+                                          (ldap.MOD_ADD,
400eba
+                                           'mail', 'user0099@dev.null')])
400eba
+    except ldap.LDAPError as e:
400eba
+        log.fatal('Failedto modify user: ' + str(e))
400eba
+        assert False
400eba
+
400eba
+    #
400eba
+    # Search using deleted attribute value- no entries should be returned
400eba
+    #
400eba
+    try:
400eba
+        entry = topology.standalone.search_s(DEFAULT_SUFFIX,
400eba
+                                             ldap.SCOPE_SUBTREE,
400eba
+                                             'mail=alias@dev.null')
400eba
+        if entry:
400eba
+            log.fatal('Entry incorrectly returned')
400eba
+            assert False
400eba
+    except ldap.LDAPError as e:
400eba
+        log.fatal('Failed to search for user: ' + str(e))
400eba
+        assert False
400eba
+
400eba
+    #
400eba
+    # Search using existing attribute value - the entry should be returned
400eba
+    #
400eba
+    try:
400eba
+        entry = topology.standalone.search_s(DEFAULT_SUFFIX,
400eba
+                                             ldap.SCOPE_SUBTREE,
400eba
+                                             'mail=user0099@dev.null')
400eba
+        if entry is None:
400eba
+            log.fatal('Entry not found, but it should have been')
400eba
+            assert False
400eba
+    except ldap.LDAPError as e:
400eba
+        log.fatal('Failed to search for user: ' + str(e))
400eba
+        assert False
400eba
+
400eba
+    #
400eba
+    # Delete the last values
400eba
+    #
400eba
+    try:
400eba
+        topology.standalone.modify_s(DN, [(ldap.MOD_DELETE,
400eba
+                                           'mail',
400eba
+                                           'user0099@dev.null'),
400eba
+                                          (ldap.MOD_DELETE,
400eba
+                                           'mail',
400eba
+                                           'user0099@redhat.com')
400eba
+                                          ])
400eba
+    except ldap.LDAPError as e:
400eba
+        log.fatal('Failed to modify user: ' + str(e))
400eba
+        assert False
400eba
+
400eba
+    #
400eba
+    # Search using deleted attribute value - no entries should be returned
400eba
+    #
400eba
+    try:
400eba
+        entry = topology.standalone.search_s(DEFAULT_SUFFIX,
400eba
+                                             ldap.SCOPE_SUBTREE,
400eba
+                                             'mail=user0099@redhat.com')
400eba
+        if entry:
400eba
+            log.fatal('Entry incorrectly returned')
400eba
+            assert False
400eba
+    except ldap.LDAPError as e:
400eba
+        log.fatal('Failed to search for user: ' + str(e))
400eba
+        assert False
400eba
+
400eba
+    #
400eba
+    # Make sure presence index is correctly updated - no entries should be
400eba
+    # returned
400eba
+    #
400eba
+    try:
400eba
+        entry = topology.standalone.search_s(DEFAULT_SUFFIX,
400eba
+                                             ldap.SCOPE_SUBTREE,
400eba
+                                             'mail=*')
400eba
+        if entry:
400eba
+            log.fatal('Entry incorrectly returned')
400eba
+            assert False
400eba
+    except ldap.LDAPError as e:
400eba
+        log.fatal('Failed to search for user: ' + str(e))
400eba
+        assert False
400eba
+
400eba
+    #
400eba
+    # Now add the attributes back, and lets run a different set of tests with
400eba
+    # a different number of attributes
400eba
+    #
400eba
+    try:
400eba
+        topology.standalone.modify_s(DN, [(ldap.MOD_ADD,
400eba
+                                           'mail',
400eba
+                                           ['user0099@dev.null',
400eba
+                                            'alias@dev.null'])])
400eba
+    except ldap.LDAPError as e:
400eba
+        log.fatal('Failedto modify user: ' + str(e))
400eba
+        assert False
400eba
+
400eba
+    #
400eba
+    # Remove and readd some attibutes
400eba
+    #
400eba
+    try:
400eba
+        topology.standalone.modify_s(DN, [(ldap.MOD_DELETE,
400eba
+                                           'mail',
400eba
+                                           'alias@dev.null'),
400eba
+                                          (ldap.MOD_DELETE,
400eba
+                                           'mail',
400eba
+                                           'user0099@dev.null'),
400eba
+                                          (ldap.MOD_ADD,
400eba
+                                           'mail', 'user0099@dev.null')])
400eba
+    except ldap.LDAPError as e:
400eba
+        log.fatal('Failedto modify user: ' + str(e))
400eba
+        assert False
400eba
+
400eba
+    #
400eba
+    # Search using deleted attribute value - no entries should be returned
400eba
+    #
400eba
+    try:
400eba
+        entry = topology.standalone.search_s(DEFAULT_SUFFIX,
400eba
+                                             ldap.SCOPE_SUBTREE,
400eba
+                                             'mail=alias@dev.null')
400eba
+        if entry:
400eba
+            log.fatal('Entry incorrectly returned')
400eba
+            assert False
400eba
+    except ldap.LDAPError as e:
400eba
+        log.fatal('Failed to search for user: ' + str(e))
400eba
+        assert False
400eba
+
400eba
+    #
400eba
+    # Search using existing attribute value - the entry should be returned
400eba
+    #
400eba
+    try:
400eba
+        entry = topology.standalone.search_s(DEFAULT_SUFFIX,
400eba
+                                             ldap.SCOPE_SUBTREE,
400eba
+                                             'mail=user0099@dev.null')
400eba
+        if entry is None:
400eba
+            log.fatal('Entry not found, but it should have been')
400eba
+            assert False
400eba
+    except ldap.LDAPError as e:
400eba
+        log.fatal('Failed to search for user: ' + str(e))
400eba
+        assert False
400eba
+
400eba
+    log.info('Test PASSED')
400eba
+
400eba
+
400eba
+if __name__ == '__main__':
400eba
+    # Run isolated
400eba
+    # -s for DEBUG mode
400eba
+    CURRENT_FILE = os.path.realpath(__file__)
400eba
+    pytest.main("-s %s" % CURRENT_FILE)
400eba
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
400eba
index 2adf2f8..00e78a7 100644
400eba
--- a/ldap/servers/slapd/back-ldbm/index.c
400eba
+++ b/ldap/servers/slapd/back-ldbm/index.c
400eba
@@ -727,31 +727,24 @@ index_add_mods(
400eba
                     flags = BE_INDEX_DEL|BE_INDEX_PRESENCE|BE_INDEX_EQUALITY;
400eba
                 } else {
400eba
                     flags = BE_INDEX_DEL;
400eba
-
400eba
-                    /* If the same value doesn't exist in a subtype, set
400eba
-                     * BE_INDEX_EQUALITY flag so the equality index is
400eba
-                     * removed.
400eba
-                     */
400eba
                     curr_attr = NULL;
400eba
                     slapi_entry_attr_find(olde->ep_entry,
400eba
-                                          mods[i]->mod_type, &curr_attr);
400eba
+                                          mods[i]->mod_type,
400eba
+                                          &curr_attr);
400eba
                     if (curr_attr) {
400eba
-                        int found = 0;
400eba
                         for (j = 0; mods_valueArray[j] != NULL; j++ ) {
400eba
-                    	    if ( slapi_valueset_find(curr_attr, all_vals, mods_valueArray[j])) {
400eba
-                                /* The same value found in evals. 
400eba
-                                 * We don't touch the equality index. */
400eba
-                                found = 1;
400eba
+                            if ( !slapi_valueset_find(curr_attr, all_vals, mods_valueArray[j]) ) {
400eba
+                                /*
400eba
+                                 * If the mod del value is not found in all_vals
400eba
+                                 * we need to update the equality index as the
400eba
+                                 * final value(s) have changed
400eba
+                                 */
400eba
+                                if (!(flags & BE_INDEX_EQUALITY)) {
400eba
+                                    flags |= BE_INDEX_EQUALITY;
400eba
+                                }
400eba
                                 break;
400eba
                             }
400eba
                         }
400eba
-                        /* 
400eba
-                         * to-be-deleted curr_attr does not exist in the 
400eba
-                         * new value set evals.  So, we can remove it.
400eba
-                         */
400eba
-                        if (!found && !(flags & BE_INDEX_EQUALITY)) {
400eba
-                            flags |= BE_INDEX_EQUALITY;
400eba
-                        }
400eba
                     } 
400eba
                 }
400eba
 
400eba
-- 
400eba
2.4.3
400eba