|
9 | 9 | import os
|
10 | 10 | import re
|
11 | 11 | import socket
|
| 12 | +import threading |
| 13 | +import time |
12 | 14 | import unittest
|
13 | 15 | import pickle
|
14 | 16 |
|
| 17 | + |
15 | 18 | # Switch off processing .ldaprc or ldap.conf before importing _ldap
|
16 | 19 | os.environ['LDAPNOINIT'] = '1'
|
17 | 20 |
|
@@ -643,6 +646,66 @@ def test105_reconnect_restore(self):
|
643 | 646 | self.server._start_slapd()
|
644 | 647 | self.assertEqual(l1.whoami_s(), 'dn:'+bind_dn)
|
645 | 648 |
|
| 649 | + def test106_reconnect_restore(self): |
| 650 | + lo = self.ldap_object_class(self.server.ldap_uri, retry_max=2, retry_delay=1) |
| 651 | + bind_dn = 'cn=user1,' + self.server.suffix |
| 652 | + lo.simple_bind_s(bind_dn, 'user1_pw') |
| 653 | + |
| 654 | + dn = lo.whoami_s()[3:] |
| 655 | + |
| 656 | + self.server._proc.terminate() |
| 657 | + self.server.wait() |
| 658 | + |
| 659 | + # do a search, wait for the timeout, handle SERVER_DOWN exception |
| 660 | + with self.assertRaises(ldap.SERVER_DOWN): |
| 661 | + lo.search_s(dn, ldap.SCOPE_BASE, '(objectClass=*)') |
| 662 | + |
| 663 | + self.server._start_slapd() |
| 664 | + |
| 665 | + # try to use the connection again |
| 666 | + lo.search_s(dn, ldap.SCOPE_BASE, '(objectClass=*)') |
| 667 | + # this used to raise ldap.INSUFFICIENT_ACCESS, as it is became a unbound connection and did everything anonymously. |
| 668 | + |
| 669 | + def test107_reconnect_restore(self): |
| 670 | + """The idea of this test is to restart the LDAP-Server while there are ongoing searches. |
| 671 | + This causes :class:`ldap.UNAVAILABLE` to be raised (with |OpenLDAP|) for a short time. |
| 672 | + To increase the chance of triggering this bug we are starting multiple threads |
| 673 | + with a large number of retry attempts in a short amount of time. |
| 674 | + """ |
| 675 | + # TODO: refactor this test |
| 676 | + excs = [] |
| 677 | + |
| 678 | + def _reconnect_search_thread(): |
| 679 | + lo = self.ldap_object_class(self.server.ldap_uri) |
| 680 | + bind_dn = 'cn=user1,' + self.server.suffix |
| 681 | + lo.simple_bind_s(bind_dn, 'user1_pw') |
| 682 | + lo._retry_max = 10E4 |
| 683 | + lo._retry_delay = .001 |
| 684 | + lo.search_ext_s(self.server.suffix, ldap.SCOPE_SUBTREE, "cn=user1", attrlist=["cn"]) |
| 685 | + s = time.time() |
| 686 | + while (time.time() - s) < run_time: |
| 687 | + lo.search_ext_s(self.server.suffix, ldap.SCOPE_SUBTREE, filterstr="cn=user1", attrlist=["cn"]) |
| 688 | + |
| 689 | + def reconnect_search_thread(): |
| 690 | + try: |
| 691 | + _reconnect_search_thread() |
| 692 | + except Exception as exc: |
| 693 | + excs.append(exc) |
| 694 | + |
| 695 | + thread_count = 100 |
| 696 | + run_time = 10.0 |
| 697 | + my_thread = [None] * thread_count |
| 698 | + for i in range(0, thread_count): |
| 699 | + my_thread[i] = threading.Thread(target=reconnect_search_thread) |
| 700 | + for t in my_thread: |
| 701 | + t.start() |
| 702 | + time.sleep(3) |
| 703 | + self.server.restart() |
| 704 | + for t in my_thread: |
| 705 | + t.join() |
| 706 | + |
| 707 | + self.assertEqual(excs, []) |
| 708 | + |
646 | 709 |
|
647 | 710 | @requires_init_fd()
|
648 | 711 | class Test03_SimpleLDAPObjectWithFileno(Test00_SimpleLDAPObject):
|
|
0 commit comments