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