andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
Blob Blame History Raw
From f82ad8baa4003e0c58711f11321513e821a7fc6f Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 7 Dec 2015 16:45:06 -0500
Subject: [PATCH 367/368] 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 5cd8f73205007ecbd44ae2fbfb5bcdf7e39c3d6e)
(cherry picked from commit 8e49d6db6973078396b869ab4ed59c565d7010a9)
(cherry picked from commit c7cf0001002da1bcabe0371d9511a014d8e2b16f)
---
 dirsrvtests/tickets/ticket48370_test.py | 236 ++++++++++++++++++++++++++++++++
 ldap/servers/slapd/back-ldbm/index.c    |  29 ++--
 2 files changed, 247 insertions(+), 18 deletions(-)
 create mode 100644 dirsrvtests/tickets/ticket48370_test.py

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 90d1d23..0b41ce4 100644
--- a/ldap/servers/slapd/back-ldbm/index.c
+++ b/ldap/servers/slapd/back-ldbm/index.c
@@ -740,31 +740,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