1
0

ticket47664_test.py 9.4 KB

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