ticket47973_test.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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 ldap.sasl
  14. import logging
  15. import pytest
  16. from lib389 import DirSrv, Entry, tools, tasks
  17. from lib389.tools import DirSrvTools
  18. from lib389._constants import *
  19. from lib389.properties import *
  20. from lib389.tasks import *
  21. log = logging.getLogger(__name__)
  22. installation_prefix = None
  23. USER_DN = 'uid=user1,%s' % (DEFAULT_SUFFIX)
  24. SCHEMA_RELOAD_COUNT = 10
  25. class TopologyStandalone(object):
  26. def __init__(self, standalone):
  27. standalone.open()
  28. self.standalone = standalone
  29. @pytest.fixture(scope="module")
  30. def topology(request):
  31. '''
  32. This fixture is used to standalone topology for the 'module'.
  33. '''
  34. global installation_prefix
  35. if installation_prefix:
  36. args_instance[SER_DEPLOYED_DIR] = installation_prefix
  37. standalone = DirSrv(verbose=False)
  38. # Args for the standalone instance
  39. args_instance[SER_HOST] = HOST_STANDALONE
  40. args_instance[SER_PORT] = PORT_STANDALONE
  41. args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
  42. args_standalone = args_instance.copy()
  43. standalone.allocate(args_standalone)
  44. # Get the status of the instance and restart it if it exists
  45. instance_standalone = standalone.exists()
  46. # Remove the instance
  47. if instance_standalone:
  48. standalone.delete()
  49. # Create the instance
  50. standalone.create()
  51. # Used to retrieve configuration information (dbdir, confdir...)
  52. standalone.open()
  53. # clear the tmp directory
  54. standalone.clearTmpDir(__file__)
  55. # Here we have standalone instance up and running
  56. return TopologyStandalone(standalone)
  57. def task_complete(conn, task_dn):
  58. finished = False
  59. try:
  60. task_entry = conn.search_s(task_dn, ldap.SCOPE_BASE, 'objectclass=*')
  61. if not task_entry:
  62. log.fatal('wait_for_task: Search failed to find task: ' + task_dn)
  63. assert False
  64. if task_entry[0].hasAttr('nstaskexitcode'):
  65. # task is done
  66. finished = True
  67. except ldap.LDAPError as e:
  68. log.fatal('wait_for_task: Search failed: ' + e.message['desc'])
  69. assert False
  70. return finished
  71. def test_ticket47973(topology):
  72. """
  73. During the schema reload task there is a small window where the new schema is not loaded
  74. into the asi hashtables - this results in searches not returning entries.
  75. """
  76. log.info('Testing Ticket 47973 - Test the searches still work as expected during schema reload tasks')
  77. #
  78. # Add a user
  79. #
  80. try:
  81. topology.standalone.add_s(Entry((USER_DN, {
  82. 'objectclass': 'top extensibleObject'.split(),
  83. 'uid': 'user1'
  84. })))
  85. except ldap.LDAPError as e:
  86. log.error('Failed to add user1: error ' + e.message['desc'])
  87. assert False
  88. #
  89. # Run a series of schema_reload tasks while searching for our user. Since
  90. # this is a race condition, run it several times.
  91. #
  92. task_count = 0
  93. while task_count < SCHEMA_RELOAD_COUNT:
  94. #
  95. # Add a schema reload task
  96. #
  97. TASK_DN = 'cn=task-' + str(task_count) + ',cn=schema reload task, cn=tasks, cn=config'
  98. try:
  99. topology.standalone.add_s(Entry((TASK_DN, {
  100. 'objectclass': 'top extensibleObject'.split(),
  101. 'cn': 'task-' + str(task_count)
  102. })))
  103. except ldap.LDAPError as e:
  104. log.error('Failed to add task entry: error ' + e.message['desc'])
  105. assert False
  106. #
  107. # While we wait for the task to complete keep searching for our user
  108. #
  109. search_count = 0
  110. while search_count < 100:
  111. #
  112. # Now check the user is still being returned
  113. #
  114. try:
  115. entries = topology.standalone.search_s(DEFAULT_SUFFIX,
  116. ldap.SCOPE_SUBTREE,
  117. '(uid=user1)')
  118. if not entries or not entries[0]:
  119. log.fatal('User was not returned from search!')
  120. assert False
  121. except ldap.LDAPError as e:
  122. log.fatal('Unable to search for entry %s: error %s' % (USER_DN, e.message['desc']))
  123. assert False
  124. #
  125. # Check if task is complete
  126. #
  127. if task_complete(topology.standalone, TASK_DN):
  128. break
  129. search_count += 1
  130. task_count += 1
  131. def test_ticket47973_final(topology):
  132. topology.standalone.delete()
  133. log.info('Testcase PASSED')
  134. def run_isolated():
  135. '''
  136. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  137. To run isolated without py.test, you need to
  138. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  139. - set the installation prefix
  140. - run this program
  141. '''
  142. global installation_prefix
  143. installation_prefix = None
  144. topo = topology(True)
  145. test_ticket47973(topo)
  146. test_ticket47973_final(topo)
  147. if __name__ == '__main__':
  148. run_isolated()