From 4a52c95b2f7815c15efd84daf57ced08e7855cc2 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
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 <ticket number> -s|--suite <suite name> ' +
- '[ i|--instances <number of standalone instances> [ -m|--masters <number of masters> ' +
- '-h|--hubs <number of hubs> -c|--consumers <number of 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 <ticket number> ' +
+ '-s|--suite <suite name> ' +
+ '[ i|--instances <number of standalone instances> ' +
+ '[ -m|--masters <number of masters> -h|--hubs <number of hubs> ' +
+ '-c|--consumers <number of 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