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. def fin():
  54. standalone.delete()
  55. request.addfinalizer(fin)
  56. # Here we have standalone instance up and running
  57. return TopologyStandalone(standalone)
  58. def task_complete(conn, task_dn):
  59. finished = False
  60. try:
  61. task_entry = conn.search_s(task_dn, ldap.SCOPE_BASE, 'objectclass=*')
  62. if not task_entry:
  63. log.fatal('wait_for_task: Search failed to find task: ' + task_dn)
  64. assert False
  65. if task_entry[0].hasAttr('nstaskexitcode'):
  66. # task is done
  67. finished = True
  68. except ldap.LDAPError as e:
  69. log.fatal('wait_for_task: Search failed: ' + e.message['desc'])
  70. assert False
  71. return finished
  72. def test_ticket47973(topology):
  73. """
  74. During the schema reload task there is a small window where the new schema is not loaded
  75. into the asi hashtables - this results in searches not returning entries.
  76. """
  77. log.info('Testing Ticket 47973 - Test the searches still work as expected during schema reload tasks')
  78. #
  79. # Add a user
  80. #
  81. try:
  82. topology.standalone.add_s(Entry((USER_DN, {
  83. 'objectclass': 'top extensibleObject'.split(),
  84. 'uid': 'user1'
  85. })))
  86. except ldap.LDAPError as e:
  87. log.error('Failed to add user1: error ' + e.message['desc'])
  88. assert False
  89. #
  90. # Run a series of schema_reload tasks while searching for our user. Since
  91. # this is a race condition, run it several times.
  92. #
  93. task_count = 0
  94. while task_count < SCHEMA_RELOAD_COUNT:
  95. #
  96. # Add a schema reload task
  97. #
  98. TASK_DN = 'cn=task-' + str(task_count) + ',cn=schema reload task, cn=tasks, cn=config'
  99. try:
  100. topology.standalone.add_s(Entry((TASK_DN, {
  101. 'objectclass': 'top extensibleObject'.split(),
  102. 'cn': 'task-' + str(task_count)
  103. })))
  104. except ldap.LDAPError as e:
  105. log.error('Failed to add task entry: error ' + e.message['desc'])
  106. assert False
  107. #
  108. # While we wait for the task to complete keep searching for our user
  109. #
  110. search_count = 0
  111. while search_count < 100:
  112. #
  113. # Now check the user is still being returned
  114. #
  115. try:
  116. entries = topology.standalone.search_s(DEFAULT_SUFFIX,
  117. ldap.SCOPE_SUBTREE,
  118. '(uid=user1)')
  119. if not entries or not entries[0]:
  120. log.fatal('User was not returned from search!')
  121. assert False
  122. except ldap.LDAPError as e:
  123. log.fatal('Unable to search for entry %s: error %s' % (USER_DN, e.message['desc']))
  124. assert False
  125. #
  126. # Check if task is complete
  127. #
  128. if task_complete(topology.standalone, TASK_DN):
  129. break
  130. search_count += 1
  131. task_count += 1
  132. def test_ticket47973_final(topology):
  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()