dirsrvtests/tests/tickets/ticket48497_test.py | 177 ++++++++++++++++++++++++++
ldap/servers/slapd/plugin_mr.c | 2
2 files changed, 179 insertions(+)
New commits:
commit 70670f2cd40bb89104819b30ab0b4e263dfcba92
Author: Thierry Bordaz <tbordaz(a)redhat.com>
Date: Fri Mar 4 18:48:07 2016 +0100
ticket: 48497 extended search without MR indexed attribute prevents later indexing
with that MR
Bug Description:
When creating a mr_indexer or a mr_filter, we first look if it exists the
registered MR (global_mr_oids)
that can handle the required oid.
If there is no registered MR, we look for a MR plugin that can handle this oid.
At the beginning no MR is registered. If the retrieved MR plugin is called to
create:
- an indexer it sets in the registered MR the indexer create
function(SLAPI_PLUGIN_MR_INDEXER_CREATE_FN)
but not the filter create function
(SLAPI_PLUGIN_MR_FILTER_CREATE_FN).
- a filter it sets in the registered MR the filter create function
(SLAPI_PLUGIN_MR_FILTER_CREATE_FN)
but not SLAPI_PLUGIN_MR_INDEXER_CREATE_FN.
The consequence is that the registered MR may be missing filter or indexer create
fn.
It ends with different wrong behaviors:
1 - for example if we index (e.g. msMatchingRule: caseExactIA5Match) it
registers 'caseExactIA5Match',
MR plugin with the indexer create function.
Then if we issue a filter with ": caseExactIA5Match:' it
will not find the registered MR
(because it is missing SLAPI_PLUGIN_MR_FILTER_CREATE_FN), so it will
register once
again the same MR plugin but this time with the filter create
function.
2 - for example if we issue a filter with ": caseExactIA5Match:'
it registers 'caseExactIA5Match',
MR plugin with the filter create function.
Then if we index 'msMatchingRule: caseExactIA5Match', it will
retrieve the registered MR plugin
but has it has no indexer create function, it fails to index.
Fix Description:
When registering a MR plugin, sets both indexer and filter create functions
https://fedorahosted.org/389/ticket/48746
Reviewed by: Mark Reynolds, Rich Megginson (thanks Mark, thanks Rich !!)
Platforms tested: F17
Flag Day: no
Doc impact: no
diff --git a/dirsrvtests/tests/tickets/ticket48497_test.py
b/dirsrvtests/tests/tickets/ticket48497_test.py
new file mode 100644
index 0000000..dd02f4c
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket48497_test.py
@@ -0,0 +1,177 @@
+import os
+import sys
+import time
+import ldap
+import logging
+#import pytest
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+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
+
+NEW_ACCOUNT = "new_account"
+MAX_ACCOUNTS = 20
+
+MIXED_VALUE="/home/mYhOmEdIrEcToRy"
+LOWER_VALUE="/home/myhomedirectory"
+HOMEDIRECTORY_INDEX = 'cn=homeDirectory,cn=index,cn=userRoot,cn=ldbm
database,cn=plugins,cn=config'
+HOMEDIRECTORY_CN="homedirectory"
+MATCHINGRULE = 'nsMatchingRule'
+UIDNUMBER_INDEX = 'cn=uidnumber,cn=index,cn=userRoot,cn=ldbm
database,cn=plugins,cn=config'
+UIDNUMBER_CN="uidnumber"
+
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)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=True)
+ if installation1_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
+ 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_ticket48497_init(topology):
+ log.info("Initialization: add dummy entries for the tests")
+ for cpt in range(MAX_ACCOUNTS):
+ name = "%s%d" % (NEW_ACCOUNT, cpt)
+ topology.standalone.add_s(Entry(("uid=%s,%s" % (name, SUFFIX), {
+ 'objectclass': "top
posixAccount".split(),
+ 'uid': name,
+ 'cn': name,
+ 'uidnumber': str(111),
+ 'gidnumber': str(222),
+ 'homedirectory':
"/home/tb_%d" % cpt})))
+
+def test_ticket48497_homeDirectory_mixed_value(topology):
+ # Set a homedirectory value with mixed case
+ name = "uid=%s1,%s" % (NEW_ACCOUNT, SUFFIX)
+ mod = [(ldap.MOD_REPLACE, 'homeDirectory', MIXED_VALUE)]
+ topology.standalone.modify_s(name, mod)
+
+def test_ticket48497_extensible_search(topology):
+ name = "uid=%s1,%s" % (NEW_ACCOUNT, SUFFIX)
+
+ # check with the exact stored value
+ log.info("Default: can retrieve an entry filter syntax with exact stored
value")
+ ent = topology.standalone.getEntry(name, ldap.SCOPE_BASE,
"(homeDirectory=%s)" % MIXED_VALUE)
+ log.info("Default: can retrieve an entry filter caseExactIA5Match with exact
stored value")
+ ent = topology.standalone.getEntry(name, ldap.SCOPE_BASE,
"(homeDirectory:caseExactIA5Match:=%s)" % MIXED_VALUE)
+
+ # check with a lower case value that is different from the stored value
+ log.info("Default: can not retrieve an entry filter syntax match with lowered
stored value")
+ try:
+ ent = topology.standalone.getEntry(name, ldap.SCOPE_BASE,
"(homeDirectory=%s)" % LOWER_VALUE)
+ assert ent is None
+ except ldap.NO_SUCH_OBJECT:
+ pass
+ log.info("Default: can not retrieve an entry filter caseExactIA5Match with
lowered stored value")
+ try:
+ ent = topology.standalone.getEntry(name, ldap.SCOPE_BASE,
"(homeDirectory:caseExactIA5Match:=%s)" % LOWER_VALUE)
+ assert ent is None
+ except ldap.NO_SUCH_OBJECT:
+ pass
+ log.info("Default: can retrieve an entry filter caseIgnoreIA5Match with lowered
stored value")
+ ent = topology.standalone.getEntry(name, ldap.SCOPE_BASE,
"(homeDirectory:caseIgnoreIA5Match:=%s)" % LOWER_VALUE)
+
+
+def test_ticket48497_homeDirectory_index_cfg(topology):
+ log.info("\n\nindex homeDirectory in caseIgnoreIA5Match and
caseExactIA5Match")
+ try:
+ ent = topology.standalone.getEntry(HOMEDIRECTORY_INDEX, ldap.SCOPE_BASE)
+ except ldap.NO_SUCH_OBJECT:
+ topology.standalone.add_s(Entry((HOMEDIRECTORY_INDEX, {
+ 'objectclass': "top
nsIndex".split(),
+ 'cn': HOMEDIRECTORY_CN,
+ 'nsSystemIndex': 'false',
+ 'nsIndexType': 'eq'})))
+# log.info("attach debugger")
+# time.sleep(60)
+
+ IGNORE_MR_NAME='caseIgnoreIA5Match'
+ EXACT_MR_NAME='caseExactIA5Match'
+ mod = [(ldap.MOD_REPLACE, MATCHINGRULE, (IGNORE_MR_NAME, EXACT_MR_NAME))]
+ topology.standalone.modify_s(HOMEDIRECTORY_INDEX, mod)
+
+def test_ticket48497_homeDirectory_index_run(topology):
+ args = {TASK_WAIT: True}
+ topology.standalone.tasks.reindex(suffix=SUFFIX, attrname='homeDirectory',
args=args)
+
+ log.info("Check indexing succeeded with a specified matching rule")
+ file_path = os.path.join(topology.standalone.prefix,
"var/log/dirsrv/slapd-%s/errors" % topology.standalone.serverid)
+ file_obj = open(file_path, "r")
+
+ # Check if the MR configuration failure occurs
+ regex = re.compile("unknown or invalid matching rule")
+ while True:
+ line = file_obj.readline()
+ found = regex.search(line)
+ if ((line == '') or (found)):
+ break
+
+ if (found):
+ log.info("The configuration of a specific MR fails")
+ log.info(line)
+ assert 0
+
+def test_ticket48497(topology):
+ """Write your testcase here...
+
+ Also, if you need any testcase initialization,
+ please, write additional fixture for that(include finalizer).
+ """
+
+ log.info('Test complete')
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+# global installation1_prefix
+# installation1_prefix = None
+# topo = topology(True)
+# test_ticket48497_init(topo)
+#
+#
+# test_ticket48497_homeDirectory_mixed_value(topo)
+# test_ticket48497_extensible_search(topo)
+# test_ticket48497_homeDirectory_index_cfg(topo)
+# test_ticket48497_homeDirectory_index_run(topo)
+
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
\ No newline at end of file
diff --git a/ldap/servers/slapd/plugin_mr.c b/ldap/servers/slapd/plugin_mr.c
index 39639e9..7745c5c 100644
--- a/ldap/servers/slapd/plugin_mr.c
+++ b/ldap/servers/slapd/plugin_mr.c
@@ -566,6 +566,7 @@ plugin_mr_filter_create (mr_filter_t* f)
pblock_init(&pb);
slapi_pblock_set(&pb, SLAPI_PLUGIN, mrp);
slapi_pblock_set(&pb, SLAPI_PLUGIN_MR_FILTER_CREATE_FN,
default_mr_filter_create);
+ slapi_pblock_set(&pb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN,
default_mr_indexer_create);
if (!(rc = attempt_mr_filter_create (f, mrp, &pb)))
{
plugin_mr_bind (f->mrf_oid, mrp); /* for future reference */
@@ -636,6 +637,7 @@ default_mr_indexer_create(Slapi_PBlock* pb)
slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, mr_wrap_mr_index_sv_fn);
slapi_pblock_set(pb, SLAPI_PLUGIN_DESTROY_FN, default_mr_indexer_destroy);
slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, default_mr_indexer_create);
+ slapi_pblock_set(pb, SLAPI_PLUGIN_MR_FILTER_CREATE_FN, default_mr_filter_create);
rc = 0;
done: