Merge remote-tracking branch 'teor/ticket28318-035' into maint-0.3.5
[tor.git] / src / test / test_rebind.py
blobc63341a681ff134d113dec2b9d3ef7b18a8ae91f
1 from __future__ import print_function
3 import errno
4 import os
5 import random
6 import socket
7 import subprocess
8 import sys
9 import time
11 LOG_TIMEOUT = 60.0
12 LOG_WAIT = 0.1
13 LOG_CHECK_LIMIT = LOG_TIMEOUT / LOG_WAIT
15 def fail(msg):
16 print('FAIL')
17 sys.exit(msg)
19 def try_connecting_to_socksport():
20 socks_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
21 if socks_socket.connect_ex(('127.0.0.1', socks_port)):
22 tor_process.terminate()
23 fail('Cannot connect to SOCKSPort')
24 socks_socket.close()
26 def wait_for_log(s):
27 log_checked = 0
28 while log_checked < LOG_CHECK_LIMIT:
29 l = tor_process.stdout.readline()
30 l = l.decode('utf8')
31 if s in l:
32 return
33 print('Tor logged: "{}", waiting for "{}"'.format(l.strip(), s))
34 # readline() returns a blank string when there is no output
35 # avoid busy-waiting
36 if len(s) == 0:
37 time.sleep(LOG_WAIT)
38 log_checked += 1
39 fail('Could not find "{}" in logs after {} seconds'.format(s, LOG_TIMEOUT))
41 def pick_random_port():
42 port = 0
43 random.seed()
45 for i in range(8):
46 port = random.randint(10000, 60000)
47 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
48 if s.connect_ex(('127.0.0.1', port)) == 0:
49 s.close()
50 else:
51 break
53 if port == 0:
54 fail('Could not find a random free port between 10000 and 60000')
56 return port
58 if sys.hexversion < 0x02070000:
59 fail("ERROR: unsupported Python version (should be >= 2.7)")
61 if sys.hexversion > 0x03000000 and sys.hexversion < 0x03010000:
62 fail("ERROR: unsupported Python3 version (should be >= 3.1)")
64 control_port = pick_random_port()
65 socks_port = pick_random_port()
67 assert control_port != 0
68 assert socks_port != 0
70 if not os.path.exists(sys.argv[1]):
71 fail('ERROR: cannot find tor at %s' % sys.argv[1])
73 tor_path = sys.argv[1]
75 tor_process = subprocess.Popen([tor_path,
76 '-ControlPort', '127.0.0.1:{}'.format(control_port),
77 '-SOCKSPort', '127.0.0.1:{}'.format(socks_port),
78 '-FetchServerDescriptors', '0'],
79 stdout=subprocess.PIPE,
80 stderr=subprocess.PIPE)
82 if tor_process == None:
83 fail('ERROR: running tor failed')
85 if len(sys.argv) < 2:
86 fail('Usage: %s <path-to-tor>' % sys.argv[0])
88 wait_for_log('Opened Control listener on')
90 try_connecting_to_socksport()
92 control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
93 if control_socket.connect_ex(('127.0.0.1', control_port)):
94 tor_process.terminate()
95 fail('Cannot connect to ControlPort')
97 control_socket.sendall('AUTHENTICATE \r\n'.encode('utf8'))
98 control_socket.sendall('SETCONF SOCKSPort=0.0.0.0:{}\r\n'.format(socks_port).encode('utf8'))
99 wait_for_log('Opened Socks listener')
101 try_connecting_to_socksport()
103 control_socket.sendall('SETCONF SOCKSPort=127.0.0.1:{}\r\n'.format(socks_port).encode('utf8'))
104 wait_for_log('Opened Socks listener')
106 try_connecting_to_socksport()
108 control_socket.sendall('SIGNAL HALT\r\n'.encode('utf8'))
110 wait_for_log('exiting cleanly')
111 print('OK')
113 try:
114 tor_process.terminate()
115 except OSError as e:
116 if e.errno == errno.ESRCH: # errno 3: No such process
117 # assume tor has already exited due to SIGNAL HALT
118 print("Tor has already exited")
119 else:
120 raise