|
|
dc8c34 |
From f82ad8baa4003e0c58711f11321513e821a7fc6f Mon Sep 17 00:00:00 2001
|
|
|
dc8c34 |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
dc8c34 |
Date: Mon, 7 Dec 2015 16:45:06 -0500
|
|
|
dc8c34 |
Subject: [PATCH 367/368] Ticket 48370 - The 'eq' index does not get updated
|
|
|
dc8c34 |
properly when deleting and re-adding attributes in
|
|
|
dc8c34 |
the same modify operation
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Bug Description: If you delete several values of the same attribute, and
|
|
|
dc8c34 |
add at least one of them back in the same operation, the
|
|
|
dc8c34 |
equality index does not get updated.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Fix Description: Modify the logic of the index code to update the index if
|
|
|
dc8c34 |
at least one of the values in the entry changes.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Also did pep8 cleanup of create_test.py
|
|
|
dc8c34 |
|
|
|
dc8c34 |
https://fedorahosted.org/389/ticket/48370
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Reviewed by: wibrown(Thanks!)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
(cherry picked from commit 63b80b5c31ebda51445c662903a28e2a79ebe60a)
|
|
|
dc8c34 |
(cherry picked from commit 5cd8f73205007ecbd44ae2fbfb5bcdf7e39c3d6e)
|
|
|
dc8c34 |
(cherry picked from commit 8e49d6db6973078396b869ab4ed59c565d7010a9)
|
|
|
dc8c34 |
(cherry picked from commit c7cf0001002da1bcabe0371d9511a014d8e2b16f)
|
|
|
dc8c34 |
---
|
|
|
dc8c34 |
dirsrvtests/tickets/ticket48370_test.py | 236 ++++++++++++++++++++++++++++++++
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/index.c | 29 ++--
|
|
|
dc8c34 |
2 files changed, 247 insertions(+), 18 deletions(-)
|
|
|
dc8c34 |
create mode 100644 dirsrvtests/tickets/ticket48370_test.py
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/dirsrvtests/tickets/ticket48370_test.py b/dirsrvtests/tickets/ticket48370_test.py
|
|
|
dc8c34 |
new file mode 100644
|
|
|
dc8c34 |
index 0000000..f5b1f47
|
|
|
dc8c34 |
--- /dev/null
|
|
|
dc8c34 |
+++ b/dirsrvtests/tickets/ticket48370_test.py
|
|
|
dc8c34 |
@@ -0,0 +1,236 @@
|
|
|
dc8c34 |
+import os
|
|
|
dc8c34 |
+import ldap
|
|
|
dc8c34 |
+import logging
|
|
|
dc8c34 |
+import pytest
|
|
|
dc8c34 |
+from lib389 import DirSrv, Entry
|
|
|
dc8c34 |
+from lib389._constants import *
|
|
|
dc8c34 |
+from lib389.properties import *
|
|
|
dc8c34 |
+from lib389.tasks import *
|
|
|
dc8c34 |
+from lib389.utils import *
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+logging.getLogger(__name__).setLevel(logging.DEBUG)
|
|
|
dc8c34 |
+log = logging.getLogger(__name__)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+installation1_prefix = None
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+class TopologyStandalone(object):
|
|
|
dc8c34 |
+ def __init__(self, standalone):
|
|
|
dc8c34 |
+ standalone.open()
|
|
|
dc8c34 |
+ self.standalone = standalone
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+@pytest.fixture(scope="module")
|
|
|
dc8c34 |
+def topology(request):
|
|
|
dc8c34 |
+ global installation1_prefix
|
|
|
dc8c34 |
+ if installation1_prefix:
|
|
|
dc8c34 |
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Creating standalone instance ...
|
|
|
dc8c34 |
+ standalone = DirSrv(verbose=False)
|
|
|
dc8c34 |
+ args_instance[SER_HOST] = HOST_STANDALONE
|
|
|
dc8c34 |
+ args_instance[SER_PORT] = PORT_STANDALONE
|
|
|
dc8c34 |
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
|
|
|
dc8c34 |
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
|
|
|
dc8c34 |
+ args_standalone = args_instance.copy()
|
|
|
dc8c34 |
+ standalone.allocate(args_standalone)
|
|
|
dc8c34 |
+ instance_standalone = standalone.exists()
|
|
|
dc8c34 |
+ if instance_standalone:
|
|
|
dc8c34 |
+ standalone.delete()
|
|
|
dc8c34 |
+ standalone.create()
|
|
|
dc8c34 |
+ standalone.open()
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Delete each instance in the end
|
|
|
dc8c34 |
+ def fin():
|
|
|
dc8c34 |
+ standalone.delete()
|
|
|
dc8c34 |
+ request.addfinalizer(fin)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Clear out the tmp dir
|
|
|
dc8c34 |
+ standalone.clearTmpDir(__file__)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ return TopologyStandalone(standalone)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+def test_ticket48370(topology):
|
|
|
dc8c34 |
+ """
|
|
|
dc8c34 |
+ Deleting attirbute values and readding a value does not properly update
|
|
|
dc8c34 |
+ the pres index. The values are not actually deleted from the index
|
|
|
dc8c34 |
+ """
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ DN = 'uid=user0099,' + DEFAULT_SUFFIX
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Add an entry
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ topology.standalone.add_s(Entry((DN, {
|
|
|
dc8c34 |
+ 'objectclass': ['top', 'person',
|
|
|
dc8c34 |
+ 'organizationalPerson',
|
|
|
dc8c34 |
+ 'inetorgperson',
|
|
|
dc8c34 |
+ 'posixAccount'],
|
|
|
dc8c34 |
+ 'givenname': 'test',
|
|
|
dc8c34 |
+ 'sn': 'user',
|
|
|
dc8c34 |
+ 'loginshell': '/bin/bash',
|
|
|
dc8c34 |
+ 'uidNumber': '10099',
|
|
|
dc8c34 |
+ 'gidNumber': '10099',
|
|
|
dc8c34 |
+ 'gecos': 'Test User',
|
|
|
dc8c34 |
+ 'mail': ['user0099@dev.null',
|
|
|
dc8c34 |
+ 'alias@dev.null',
|
|
|
dc8c34 |
+ 'user0099@redhat.com'],
|
|
|
dc8c34 |
+ 'cn': 'Test User',
|
|
|
dc8c34 |
+ 'homeDirectory': '/home/user0099',
|
|
|
dc8c34 |
+ 'uid': 'admin2',
|
|
|
dc8c34 |
+ 'userpassword': 'password'})))
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Perform modify (delete & add mail attributes)
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ topology.standalone.modify_s(DN, [(ldap.MOD_DELETE,
|
|
|
dc8c34 |
+ 'mail',
|
|
|
dc8c34 |
+ 'user0099@dev.null'),
|
|
|
dc8c34 |
+ (ldap.MOD_DELETE,
|
|
|
dc8c34 |
+ 'mail',
|
|
|
dc8c34 |
+ 'alias@dev.null'),
|
|
|
dc8c34 |
+ (ldap.MOD_ADD,
|
|
|
dc8c34 |
+ 'mail', 'user0099@dev.null')])
|
|
|
dc8c34 |
+ except ldap.LDAPError as e:
|
|
|
dc8c34 |
+ log.fatal('Failedto modify user: ' + str(e))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Search using deleted attribute value- no entries should be returned
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ entry = topology.standalone.search_s(DEFAULT_SUFFIX,
|
|
|
dc8c34 |
+ ldap.SCOPE_SUBTREE,
|
|
|
dc8c34 |
+ 'mail=alias@dev.null')
|
|
|
dc8c34 |
+ if entry:
|
|
|
dc8c34 |
+ log.fatal('Entry incorrectly returned')
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+ except ldap.LDAPError as e:
|
|
|
dc8c34 |
+ log.fatal('Failed to search for user: ' + str(e))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Search using existing attribute value - the entry should be returned
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ entry = topology.standalone.search_s(DEFAULT_SUFFIX,
|
|
|
dc8c34 |
+ ldap.SCOPE_SUBTREE,
|
|
|
dc8c34 |
+ 'mail=user0099@dev.null')
|
|
|
dc8c34 |
+ if entry is None:
|
|
|
dc8c34 |
+ log.fatal('Entry not found, but it should have been')
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+ except ldap.LDAPError as e:
|
|
|
dc8c34 |
+ log.fatal('Failed to search for user: ' + str(e))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Delete the last values
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ topology.standalone.modify_s(DN, [(ldap.MOD_DELETE,
|
|
|
dc8c34 |
+ 'mail',
|
|
|
dc8c34 |
+ 'user0099@dev.null'),
|
|
|
dc8c34 |
+ (ldap.MOD_DELETE,
|
|
|
dc8c34 |
+ 'mail',
|
|
|
dc8c34 |
+ 'user0099@redhat.com')
|
|
|
dc8c34 |
+ ])
|
|
|
dc8c34 |
+ except ldap.LDAPError as e:
|
|
|
dc8c34 |
+ log.fatal('Failed to modify user: ' + str(e))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Search using deleted attribute value - no entries should be returned
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ entry = topology.standalone.search_s(DEFAULT_SUFFIX,
|
|
|
dc8c34 |
+ ldap.SCOPE_SUBTREE,
|
|
|
dc8c34 |
+ 'mail=user0099@redhat.com')
|
|
|
dc8c34 |
+ if entry:
|
|
|
dc8c34 |
+ log.fatal('Entry incorrectly returned')
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+ except ldap.LDAPError as e:
|
|
|
dc8c34 |
+ log.fatal('Failed to search for user: ' + str(e))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Make sure presence index is correctly updated - no entries should be
|
|
|
dc8c34 |
+ # returned
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ entry = topology.standalone.search_s(DEFAULT_SUFFIX,
|
|
|
dc8c34 |
+ ldap.SCOPE_SUBTREE,
|
|
|
dc8c34 |
+ 'mail=*')
|
|
|
dc8c34 |
+ if entry:
|
|
|
dc8c34 |
+ log.fatal('Entry incorrectly returned')
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+ except ldap.LDAPError as e:
|
|
|
dc8c34 |
+ log.fatal('Failed to search for user: ' + str(e))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Now add the attributes back, and lets run a different set of tests with
|
|
|
dc8c34 |
+ # a different number of attributes
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ topology.standalone.modify_s(DN, [(ldap.MOD_ADD,
|
|
|
dc8c34 |
+ 'mail',
|
|
|
dc8c34 |
+ ['user0099@dev.null',
|
|
|
dc8c34 |
+ 'alias@dev.null'])])
|
|
|
dc8c34 |
+ except ldap.LDAPError as e:
|
|
|
dc8c34 |
+ log.fatal('Failedto modify user: ' + str(e))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Remove and readd some attibutes
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ topology.standalone.modify_s(DN, [(ldap.MOD_DELETE,
|
|
|
dc8c34 |
+ 'mail',
|
|
|
dc8c34 |
+ 'alias@dev.null'),
|
|
|
dc8c34 |
+ (ldap.MOD_DELETE,
|
|
|
dc8c34 |
+ 'mail',
|
|
|
dc8c34 |
+ 'user0099@dev.null'),
|
|
|
dc8c34 |
+ (ldap.MOD_ADD,
|
|
|
dc8c34 |
+ 'mail', 'user0099@dev.null')])
|
|
|
dc8c34 |
+ except ldap.LDAPError as e:
|
|
|
dc8c34 |
+ log.fatal('Failedto modify user: ' + str(e))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Search using deleted attribute value - no entries should be returned
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ entry = topology.standalone.search_s(DEFAULT_SUFFIX,
|
|
|
dc8c34 |
+ ldap.SCOPE_SUBTREE,
|
|
|
dc8c34 |
+ 'mail=alias@dev.null')
|
|
|
dc8c34 |
+ if entry:
|
|
|
dc8c34 |
+ log.fatal('Entry incorrectly returned')
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+ except ldap.LDAPError as e:
|
|
|
dc8c34 |
+ log.fatal('Failed to search for user: ' + str(e))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Search using existing attribute value - the entry should be returned
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ entry = topology.standalone.search_s(DEFAULT_SUFFIX,
|
|
|
dc8c34 |
+ ldap.SCOPE_SUBTREE,
|
|
|
dc8c34 |
+ 'mail=user0099@dev.null')
|
|
|
dc8c34 |
+ if entry is None:
|
|
|
dc8c34 |
+ log.fatal('Entry not found, but it should have been')
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+ except ldap.LDAPError as e:
|
|
|
dc8c34 |
+ log.fatal('Failed to search for user: ' + str(e))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ log.info('Test PASSED')
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+if __name__ == '__main__':
|
|
|
dc8c34 |
+ # Run isolated
|
|
|
dc8c34 |
+ # -s for DEBUG mode
|
|
|
dc8c34 |
+ CURRENT_FILE = os.path.realpath(__file__)
|
|
|
dc8c34 |
+ pytest.main("-s %s" % CURRENT_FILE)
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
|
|
|
dc8c34 |
index 90d1d23..0b41ce4 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/index.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/index.c
|
|
|
dc8c34 |
@@ -740,31 +740,24 @@ index_add_mods(
|
|
|
dc8c34 |
flags = BE_INDEX_DEL|BE_INDEX_PRESENCE|BE_INDEX_EQUALITY;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
flags = BE_INDEX_DEL;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- /* If the same value doesn't exist in a subtype, set
|
|
|
dc8c34 |
- * BE_INDEX_EQUALITY flag so the equality index is
|
|
|
dc8c34 |
- * removed.
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
curr_attr = NULL;
|
|
|
dc8c34 |
slapi_entry_attr_find(olde->ep_entry,
|
|
|
dc8c34 |
- mods[i]->mod_type, &curr_attr);
|
|
|
dc8c34 |
+ mods[i]->mod_type,
|
|
|
dc8c34 |
+ &curr_attr);
|
|
|
dc8c34 |
if (curr_attr) {
|
|
|
dc8c34 |
- int found = 0;
|
|
|
dc8c34 |
for (j = 0; mods_valueArray[j] != NULL; j++ ) {
|
|
|
dc8c34 |
- if ( slapi_valueset_find(curr_attr, all_vals, mods_valueArray[j])) {
|
|
|
dc8c34 |
- /* The same value found in evals.
|
|
|
dc8c34 |
- * We don't touch the equality index. */
|
|
|
dc8c34 |
- found = 1;
|
|
|
dc8c34 |
+ if ( !slapi_valueset_find(curr_attr, all_vals, mods_valueArray[j]) ) {
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * If the mod del value is not found in all_vals
|
|
|
dc8c34 |
+ * we need to update the equality index as the
|
|
|
dc8c34 |
+ * final value(s) have changed
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ if (!(flags & BE_INDEX_EQUALITY)) {
|
|
|
dc8c34 |
+ flags |= BE_INDEX_EQUALITY;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- /*
|
|
|
dc8c34 |
- * to-be-deleted curr_attr does not exist in the
|
|
|
dc8c34 |
- * new value set evals. So, we can remove it.
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
- if (!found && !(flags & BE_INDEX_EQUALITY)) {
|
|
|
dc8c34 |
- flags |= BE_INDEX_EQUALITY;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
--
|
|
|
dc8c34 |
2.4.3
|
|
|
dc8c34 |
|