1
0

ticket47824_test.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. import os
  2. import sys
  3. import time
  4. import ldap
  5. import logging
  6. import socket
  7. import time
  8. import logging
  9. import pytest
  10. from lib389 import DirSrv, Entry, tools, tasks
  11. from lib389.tools import DirSrvTools
  12. from lib389._constants import *
  13. from lib389.properties import *
  14. from lib389.tasks import *
  15. from constants import *
  16. from ldap.controls import SimplePagedResultsControl
  17. log = logging.getLogger(__name__)
  18. installation_prefix = None
  19. MYSUFFIX = 'o=ticket47824.org'
  20. MYSUFFIXBE = 'ticket47824'
  21. SUBSUFFIX0 = 'ou=OU0,o=ticket47824.org'
  22. SUBSUFFIX0BE = 'OU0'
  23. SUBSUFFIX1 = 'ou=OU1,o=ticket47824.org'
  24. SUBSUFFIX1BE = 'OU1'
  25. SUBSUFFIX2 = 'ou=OU2,o=ticket47824.org'
  26. SUBSUFFIX2BE = 'OU2'
  27. _MYLDIF = 'ticket47824.ldif'
  28. _SUBLDIF0TMP = 'ticket47824_0.tmp'
  29. _SUBLDIF0 = 'ticket47824_0.ldif'
  30. _SUBLDIF1TMP = 'ticket47824_1.tmp'
  31. _SUBLDIF1 = 'ticket47824_1.ldif'
  32. _SUBLDIF2TMP = 'ticket47824_2.tmp'
  33. _SUBLDIF2 = 'ticket47824_2.ldif'
  34. SEARCHFILTER = '(objectclass=*)'
  35. class TopologyStandalone(object):
  36. def __init__(self, standalone):
  37. standalone.open()
  38. self.standalone = standalone
  39. @pytest.fixture(scope="module")
  40. def topology(request):
  41. '''
  42. This fixture is used to standalone topology for the 'module'.
  43. At the beginning, It may exists a standalone instance.
  44. It may also exists a backup for the standalone instance.
  45. Principle:
  46. If standalone instance exists:
  47. restart it
  48. If backup of standalone exists:
  49. create/rebind to standalone
  50. restore standalone instance from backup
  51. else:
  52. Cleanup everything
  53. remove instance
  54. remove backup
  55. Create instance
  56. Create backup
  57. '''
  58. global installation_prefix
  59. if installation_prefix:
  60. args_instance[SER_DEPLOYED_DIR] = installation_prefix
  61. standalone = DirSrv(verbose=False)
  62. # Args for the standalone instance
  63. args_instance[SER_HOST] = HOST_STANDALONE
  64. args_instance[SER_PORT] = PORT_STANDALONE
  65. args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
  66. args_standalone = args_instance.copy()
  67. standalone.allocate(args_standalone)
  68. # Get the status of the backups
  69. backup_standalone = standalone.checkBackupFS()
  70. # Get the status of the instance and restart it if it exists
  71. instance_standalone = standalone.exists()
  72. if instance_standalone:
  73. # assuming the instance is already stopped, just wait 5 sec max
  74. standalone.stop(timeout=5)
  75. standalone.start(timeout=10)
  76. if backup_standalone:
  77. # The backup exist, assuming it is correct
  78. # we just re-init the instance with it
  79. if not instance_standalone:
  80. standalone.create()
  81. # Used to retrieve configuration information (dbdir, confdir...)
  82. standalone.open()
  83. # restore standalone instance from backup
  84. standalone.stop(timeout=10)
  85. standalone.restoreFS(backup_standalone)
  86. standalone.start(timeout=10)
  87. else:
  88. # We should be here only in two conditions
  89. # - This is the first time a test involve standalone instance
  90. # - Something weird happened (instance/backup destroyed)
  91. # so we discard everything and recreate all
  92. # Remove the backup. So even if we have a specific backup file
  93. # (e.g backup_standalone) we clear backup that an instance may have created
  94. if backup_standalone:
  95. standalone.clearBackupFS()
  96. # Remove the instance
  97. if instance_standalone:
  98. standalone.delete()
  99. # Create the instance
  100. standalone.create()
  101. # Used to retrieve configuration information (dbdir, confdir...)
  102. standalone.open()
  103. # Time to create the backups
  104. standalone.stop(timeout=10)
  105. standalone.backupfile = standalone.backupFS()
  106. standalone.start(timeout=10)
  107. # clear the tmp directory
  108. standalone.clearTmpDir(__file__)
  109. #
  110. # Here we have standalone instance up and running
  111. # Either coming from a backup recovery
  112. # or from a fresh (re)init
  113. # Time to return the topology
  114. return TopologyStandalone(standalone)
  115. def test_ticket47824_run(topology):
  116. """
  117. Add 3 sub suffixes under the primary suffix
  118. Import 16 entries each
  119. Search with Simple Paged Results Control from the primary suffix (pagesize = 4)
  120. If all of them are returned, the bug is verified
  121. """
  122. log.info('Testing Ticket 47824 - paged results control is not working in some cases when we have a subsuffix')
  123. # bind as directory manager
  124. topology.standalone.log.info("Bind as %s" % DN_DM)
  125. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  126. topology.standalone.log.info("\n\n######################### SETUP SUFFIX o=ticket47824.org ######################\n")
  127. topology.standalone.backend.create(MYSUFFIX, {BACKEND_NAME: MYSUFFIXBE})
  128. topology.standalone.mappingtree.create(MYSUFFIX, bename=MYSUFFIXBE)
  129. topology.standalone.log.info("\n\n######################### SETUP SUB SUFFIX ou=OU0 ######################\n")
  130. topology.standalone.backend.create(SUBSUFFIX0, {BACKEND_NAME: SUBSUFFIX0BE})
  131. topology.standalone.mappingtree.create(SUBSUFFIX0, bename=SUBSUFFIX0BE, parent=MYSUFFIX)
  132. topology.standalone.log.info("\n\n######################### SETUP SUB SUFFIX ou=OU1 ######################\n")
  133. topology.standalone.backend.create(SUBSUFFIX1, {BACKEND_NAME: SUBSUFFIX1BE})
  134. topology.standalone.mappingtree.create(SUBSUFFIX1, bename=SUBSUFFIX1BE, parent=MYSUFFIX)
  135. topology.standalone.log.info("\n\n######################### SETUP SUB SUFFIX ou=OU2 ######################\n")
  136. topology.standalone.backend.create(SUBSUFFIX2, {BACKEND_NAME: SUBSUFFIX2BE})
  137. topology.standalone.mappingtree.create(SUBSUFFIX2, bename=SUBSUFFIX2BE, parent=MYSUFFIX)
  138. topology.standalone.log.info("\n\n######################### Generate Test data ######################\n")
  139. # get tmp dir
  140. mytmp = topology.standalone.getDir(__file__, TMP_DIR)
  141. if mytmp == None:
  142. mytmp = "/tmp"
  143. MYLDIF = '%s%s' % (mytmp, _MYLDIF)
  144. SUBLDIF0TMP = '%s%s' % (mytmp, _SUBLDIF0TMP)
  145. SUBLDIF0 = '%s%s' % (mytmp, _SUBLDIF0)
  146. SUBLDIF1TMP = '%s%s' % (mytmp, _SUBLDIF1TMP)
  147. SUBLDIF1 = '%s%s' % (mytmp, _SUBLDIF1)
  148. SUBLDIF2TMP = '%s%s' % (mytmp, _SUBLDIF2TMP)
  149. SUBLDIF2 = '%s%s' % (mytmp, _SUBLDIF2)
  150. os.system('ls %s' % MYLDIF)
  151. os.system('ls %s' % SUBLDIF0TMP)
  152. os.system('ls %s' % SUBLDIF1TMP)
  153. os.system('ls %s' % SUBLDIF2TMP)
  154. os.system('rm -f %s' % MYLDIF)
  155. os.system('rm -f %s' % SUBLDIF0TMP)
  156. os.system('rm -f %s' % SUBLDIF1TMP)
  157. os.system('rm -f %s' % SUBLDIF2TMP)
  158. os.system('dbgen.pl -s %s -o %s -n 10' % (MYSUFFIX, MYLDIF))
  159. os.system('dbgen.pl -s %s -o %s -n 10' % (SUBSUFFIX0, SUBLDIF0TMP))
  160. os.system('dbgen.pl -s %s -o %s -n 10' % (SUBSUFFIX1, SUBLDIF1TMP))
  161. os.system('dbgen.pl -s %s -o %s -n 10' % (SUBSUFFIX2, SUBLDIF2TMP))
  162. os.system('cat %s | sed -e "s/\<objectClass: organization\>/objectClass: organizationalUnit/" | sed -e "/^o:.*/d" > %s' % (SUBLDIF0TMP, SUBLDIF0))
  163. os.system('cat %s | sed -e "s/\<objectClass: organization\>/objectClass: organizationalUnit/" | sed -e "/^o:.*/d" > %s' % (SUBLDIF1TMP, SUBLDIF1))
  164. os.system('cat %s | sed -e "s/\<objectClass: organization\>/objectClass: organizationalUnit/" | sed -e "/^o:.*/d" > %s' % (SUBLDIF2TMP, SUBLDIF2))
  165. cmdline = 'egrep dn: %s %s %s %s | wc -l' % (MYLDIF, SUBLDIF0, SUBLDIF1, SUBLDIF2)
  166. p = os.popen(cmdline, "r")
  167. dnnumstr = p.readline()
  168. dnnum = int(dnnumstr)
  169. topology.standalone.log.info("We have %d entries.\n", dnnum)
  170. topology.standalone.log.info("\n\n######################### Import Test data ######################\n")
  171. args = {TASK_WAIT: True}
  172. importTask = Tasks(topology.standalone)
  173. importTask.importLDIF(MYSUFFIX, MYSUFFIXBE, MYLDIF, args)
  174. importTask.importLDIF(SUBSUFFIX0, SUBSUFFIX0BE, SUBLDIF0, args)
  175. importTask.importLDIF(SUBSUFFIX1, SUBSUFFIX1BE, SUBLDIF1, args)
  176. importTask.importLDIF(SUBSUFFIX2, SUBSUFFIX2BE, SUBLDIF2, args)
  177. topology.standalone.log.info("\n\n######################### SEARCH ALL ######################\n")
  178. topology.standalone.log.info("Bind as %s and add the READ/SEARCH SELFDN aci" % DN_DM)
  179. topology.standalone.simple_bind_s(DN_DM, PASSWORD)
  180. entries = topology.standalone.search_s(MYSUFFIX, ldap.SCOPE_SUBTREE, SEARCHFILTER)
  181. topology.standalone.log.info("Returned %d entries.\n", len(entries))
  182. #print entries
  183. assert dnnum == len(entries)
  184. topology.standalone.log.info('%d entries are successfully imported.' % dnnum)
  185. topology.standalone.log.info("\n\n######################### SEARCH WITH SIMPLE PAGED RESULTS CONTROL ######################\n")
  186. page_size = 4
  187. 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, ldap.SCOPE_SUBTREE, SEARCHFILTER, None, serverctrls=[req_ctrl])
  193. pageddncnt = 0
  194. pages = 0
  195. while True:
  196. pages += 1
  197. topology.standalone.log.info("Getting page %d" % pages)
  198. rtype, rdata, rmsgid, serverctrls = topology.standalone.result3(msgid, resp_ctrl_classes=known_ldap_resp_ctrls)
  199. topology.standalone.log.info("%d results" % len(rdata))
  200. pageddncnt += len(rdata)
  201. topology.standalone.log.info("Results:")
  202. for dn, attrs in rdata:
  203. topology.standalone.log.info("dn: %s" % dn)
  204. pctrls = [
  205. c for c in serverctrls if c.controlType == SimplePagedResultsControl.controlType
  206. ]
  207. if not pctrls:
  208. topology.standalone.log.info('Warning: Server ignores RFC 2696 control.')
  209. break
  210. if pctrls[0].cookie:
  211. req_ctrl.cookie = pctrls[0].cookie
  212. topology.standalone.log.info("cookie: %s" % req_ctrl.cookie)
  213. msgid = topology.standalone.search_ext(MYSUFFIX,
  214. ldap.SCOPE_SUBTREE,
  215. SEARCHFILTER,
  216. None,
  217. serverctrls=[req_ctrl])
  218. else:
  219. topology.standalone.log.info("No cookie")
  220. break
  221. topology.standalone.log.info("Paged result search returned %d entries.\n", pageddncnt)
  222. assert dnnum == len(entries)
  223. topology.standalone.log.info("ticket47824 was successfully verified.");
  224. def test_ticket47824_final(topology):
  225. topology.standalone.stop(timeout=10)
  226. def run_isolated():
  227. '''
  228. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  229. To run isolated without py.test, you need to
  230. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  231. - set the installation prefix
  232. - run this program
  233. '''
  234. global installation_prefix
  235. installation_prefix = None
  236. topo = topology(True)
  237. test_ticket47824_run(topo)
  238. test_ticket47824_final(topo)
  239. if __name__ == '__main__':
  240. run_isolated()