andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
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