ticket48191_test.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. # --- BEGIN COPYRIGHT BLOCK ---
  2. # Copyright (C) 2015 Red Hat, Inc.
  3. # All rights reserved.
  4. #
  5. # License: GPL (version 3 or any later version).
  6. # See LICENSE for details.
  7. # --- END COPYRIGHT BLOCK ---
  8. #
  9. import os
  10. import sys
  11. import time
  12. import ldap
  13. import logging
  14. import pytest
  15. from lib389 import DirSrv, Entry, tools, tasks
  16. from lib389.tools import DirSrvTools
  17. from lib389._constants import *
  18. from lib389.properties import *
  19. from lib389.tasks import *
  20. from ldap.controls import SimplePagedResultsControl
  21. from ldap.controls.simple import GetEffectiveRightsControl
  22. log = logging.getLogger(__name__)
  23. installation_prefix = None
  24. CONFIG_DN = 'cn=config'
  25. MYSUFFIX = 'o=ticket48191.org'
  26. MYSUFFIXBE = 'ticket48191'
  27. _MYLDIF = 'ticket48191.ldif'
  28. SEARCHFILTER = '(objectclass=*)'
  29. class TopologyStandalone(object):
  30. def __init__(self, standalone):
  31. standalone.open()
  32. self.standalone = standalone
  33. @pytest.fixture(scope="module")
  34. def topology(request):
  35. '''
  36. This fixture is used to standalone topology for the 'module'.
  37. '''
  38. global installation_prefix
  39. if installation_prefix:
  40. args_instance[SER_DEPLOYED_DIR] = installation_prefix
  41. standalone = DirSrv(verbose=False)
  42. # Args for the standalone instance
  43. args_instance[SER_HOST] = HOST_STANDALONE
  44. args_instance[SER_PORT] = PORT_STANDALONE
  45. args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
  46. args_standalone = args_instance.copy()
  47. standalone.allocate(args_standalone)
  48. # Get the status of the instance and restart it if it exists
  49. instance_standalone = standalone.exists()
  50. # Remove the instance
  51. if instance_standalone:
  52. standalone.delete()
  53. # Create the instance
  54. standalone.create()
  55. # Used to retrieve configuration information (dbdir, confdir...)
  56. standalone.open()
  57. # clear the tmp directory
  58. standalone.clearTmpDir(__file__)
  59. # Here we have standalone instance up and running
  60. return TopologyStandalone(standalone)
  61. def test_ticket48191_setup(topology):
  62. """
  63. Import 20 entries
  64. Set nsslapd-maxsimplepaged-per-conn in cn=config
  65. If the val is negative, no limit.
  66. If the value is 0, the simple paged results is disabled.
  67. If the value is positive, the value is the max simple paged results requests per connection.
  68. The setting has to be dynamic.
  69. """
  70. log.info('Testing Ticket 48191 - Config parameter nsslapd-maxsimplepaged-per-conn')
  71. # bind as directory manager
  72. topology.standalone.log.info("Bind as %s" % DN_DM)
  73. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  74. topology.standalone.log.info("\n\n######################### SETUP SUFFIX o=ticket48191.org ######################\n")
  75. topology.standalone.backend.create(MYSUFFIX, {BACKEND_NAME: MYSUFFIXBE})
  76. topology.standalone.mappingtree.create(MYSUFFIX, bename=MYSUFFIXBE)
  77. topology.standalone.log.info("\n\n######################### Generate Test data ######################\n")
  78. # get tmp dir
  79. mytmp = topology.standalone.getDir(__file__, TMP_DIR)
  80. if mytmp is None:
  81. mytmp = "/tmp"
  82. MYLDIF = '%s%s' % (mytmp, _MYLDIF)
  83. os.system('ls %s' % MYLDIF)
  84. os.system('rm -f %s' % MYLDIF)
  85. if hasattr(topology.standalone, 'prefix'):
  86. prefix = topology.standalone.prefix
  87. else:
  88. prefix = None
  89. dbgen_prog = prefix + '/bin/dbgen.pl'
  90. topology.standalone.log.info('dbgen_prog: %s' % dbgen_prog)
  91. os.system('%s -s %s -o %s -n 14' % (dbgen_prog, MYSUFFIX, MYLDIF))
  92. cmdline = 'egrep dn: %s | wc -l' % MYLDIF
  93. p = os.popen(cmdline, "r")
  94. dnnumstr = p.readline()
  95. global dnnum
  96. dnnum = int(dnnumstr)
  97. topology.standalone.log.info("We have %d entries.\n", dnnum)
  98. topology.standalone.log.info("\n\n######################### Import Test data ######################\n")
  99. args = {TASK_WAIT: True}
  100. importTask = Tasks(topology.standalone)
  101. importTask.importLDIF(MYSUFFIX, MYSUFFIXBE, MYLDIF, args)
  102. topology.standalone.log.info("\n\n######################### SEARCH ALL ######################\n")
  103. topology.standalone.log.info("Bind as %s and add the READ/SEARCH SELFDN aci" % DN_DM)
  104. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  105. global entries
  106. entries = topology.standalone.search_s(MYSUFFIX, ldap.SCOPE_SUBTREE, SEARCHFILTER)
  107. topology.standalone.log.info("Returned %d entries.\n", len(entries))
  108. #print entries
  109. assert dnnum == len(entries)
  110. topology.standalone.log.info('%d entries are successfully imported.' % dnnum)
  111. def test_ticket48191_run_0(topology):
  112. topology.standalone.log.info("\n\n######################### SEARCH WITH SIMPLE PAGED RESULTS CONTROL (no nsslapd-maxsimplepaged-per-conn) ######################\n")
  113. page_size = 4
  114. spr_req_ctrl = SimplePagedResultsControl(True, size=page_size, cookie='')
  115. known_ldap_resp_ctrls = {
  116. SimplePagedResultsControl.controlType: SimplePagedResultsControl,
  117. }
  118. topology.standalone.log.info("Calling search_ext...")
  119. msgid = topology.standalone.search_ext(MYSUFFIX,
  120. ldap.SCOPE_SUBTREE,
  121. SEARCHFILTER,
  122. ['cn'],
  123. serverctrls=[spr_req_ctrl])
  124. pageddncnt = 0
  125. pages = 0
  126. while True:
  127. pages += 1
  128. topology.standalone.log.info("Getting page %d" % pages)
  129. rtype, rdata, rmsgid, responcectrls = topology.standalone.result3(msgid, resp_ctrl_classes=known_ldap_resp_ctrls)
  130. topology.standalone.log.info("%d results" % len(rdata))
  131. pageddncnt += len(rdata)
  132. topology.standalone.log.info("Results:")
  133. for dn, attrs in rdata:
  134. topology.standalone.log.info("dn: %s" % dn)
  135. pctrls = [
  136. c for c in responcectrls if c.controlType == SimplePagedResultsControl.controlType
  137. ]
  138. if not pctrls:
  139. topology.standalone.log.info('Warning: Server ignores RFC 2696 control.')
  140. break
  141. if pctrls[0].cookie:
  142. spr_req_ctrl.cookie = pctrls[0].cookie
  143. topology.standalone.log.info("cookie: %s" % spr_req_ctrl.cookie)
  144. msgid = topology.standalone.search_ext(MYSUFFIX,
  145. ldap.SCOPE_SUBTREE,
  146. SEARCHFILTER,
  147. ['cn'],
  148. serverctrls=[spr_req_ctrl])
  149. else:
  150. topology.standalone.log.info("No cookie")
  151. break
  152. topology.standalone.log.info("Paged result search returned %d entries in %d pages.\n", pageddncnt, pages)
  153. global dnnum
  154. global entries
  155. assert dnnum == len(entries)
  156. assert pages == (dnnum / page_size)
  157. def test_ticket48191_run_1(topology):
  158. topology.standalone.log.info("\n\n######################### SEARCH WITH SIMPLE PAGED RESULTS CONTROL (nsslapd-maxsimplepaged-per-conn: 0) ######################\n")
  159. topology.standalone.modify_s(CONFIG_DN, [(ldap.MOD_REPLACE, 'nsslapd-maxsimplepaged-per-conn', '0')])
  160. page_size = 4
  161. spr_req_ctrl = SimplePagedResultsControl(True, size=page_size, cookie='')
  162. known_ldap_resp_ctrls = {
  163. SimplePagedResultsControl.controlType: SimplePagedResultsControl,
  164. }
  165. topology.standalone.log.info("Calling search_ext...")
  166. msgid = topology.standalone.search_ext(MYSUFFIX,
  167. ldap.SCOPE_SUBTREE,
  168. SEARCHFILTER,
  169. ['cn'],
  170. serverctrls=[spr_req_ctrl])
  171. topology.standalone.log.fatal('Unexpected success')
  172. try:
  173. rtype, rdata, rmsgid, responcectrls = topology.standalone.result3(msgid, resp_ctrl_classes=known_ldap_resp_ctrls)
  174. except ldap.UNWILLING_TO_PERFORM as e:
  175. topology.standalone.log.info('Returned the expected RC UNWILLING_TO_PERFORM')
  176. return
  177. except ldap.LDAPError as e:
  178. topology.standalone.log.fatal('Unexpected error: ' + e.message['desc'])
  179. assert False
  180. topology.standalone.log.info("Type %d" % rtype)
  181. topology.standalone.log.info("%d results" % len(rdata))
  182. assert False
  183. def test_ticket48191_run_2(topology):
  184. topology.standalone.log.info("\n\n######################### SEARCH WITH SIMPLE PAGED RESULTS CONTROL (nsslapd-maxsimplepaged-per-conn: 1000) ######################\n")
  185. topology.standalone.modify_s(CONFIG_DN, [(ldap.MOD_REPLACE, 'nsslapd-maxsimplepaged-per-conn', '1000')])
  186. page_size = 4
  187. spr_req_ctrl = SimplePagedResultsControl(True, size=page_size, cookie='')
  188. known_ldap_resp_ctrls = {
  189. SimplePagedResultsControl.controlType: SimplePagedResultsControl,
  190. }
  191. topology.standalone.log.info("Calling search_ext...")
  192. msgid = topology.standalone.search_ext(MYSUFFIX,
  193. ldap.SCOPE_SUBTREE,
  194. SEARCHFILTER,
  195. ['cn'],
  196. serverctrls=[spr_req_ctrl])
  197. pageddncnt = 0
  198. pages = 0
  199. while True:
  200. pages += 1
  201. topology.standalone.log.info("Getting page %d" % pages)
  202. rtype, rdata, rmsgid, responcectrls = topology.standalone.result3(msgid, resp_ctrl_classes=known_ldap_resp_ctrls)
  203. topology.standalone.log.info("%d results" % len(rdata))
  204. pageddncnt += len(rdata)
  205. topology.standalone.log.info("Results:")
  206. for dn, attrs in rdata:
  207. topology.standalone.log.info("dn: %s" % dn)
  208. pctrls = [
  209. c for c in responcectrls if c.controlType == SimplePagedResultsControl.controlType
  210. ]
  211. if not pctrls:
  212. topology.standalone.log.info('Warning: Server ignores RFC 2696 control.')
  213. break
  214. if pctrls[0].cookie:
  215. spr_req_ctrl.cookie = pctrls[0].cookie
  216. topology.standalone.log.info("cookie: %s" % spr_req_ctrl.cookie)
  217. msgid = topology.standalone.search_ext(MYSUFFIX,
  218. ldap.SCOPE_SUBTREE,
  219. SEARCHFILTER,
  220. ['cn'],
  221. serverctrls=[spr_req_ctrl])
  222. else:
  223. topology.standalone.log.info("No cookie")
  224. break
  225. topology.standalone.log.info("Paged result search returned %d entries in %d pages.\n", pageddncnt, pages)
  226. global dnnum
  227. global entries
  228. assert dnnum == len(entries)
  229. assert pages == (dnnum / page_size)
  230. topology.standalone.log.info("ticket48191 was successfully verified.")
  231. def test_ticket48191_final(topology):
  232. topology.standalone.delete()
  233. log.info('Testcase PASSED')
  234. def run_isolated():
  235. '''
  236. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  237. To run isolated without py.test, you need to
  238. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  239. - set the installation prefix
  240. - run this program
  241. '''
  242. global installation_prefix
  243. installation_prefix = None
  244. topo = topology(True)
  245. test_ticket48191_setup(topo)
  246. test_ticket48191_run_0(topo)
  247. test_ticket48191_run_1(topo)
  248. test_ticket48191_run_2(topo)
  249. test_ticket48191_final(topo)
  250. if __name__ == '__main__':
  251. run_isolated()