Add python-eventlet 0.16.1
[packages/trusty/python-eventlet.git] / eventlet / tests / ssl_test.py
1 import socket
2 import warnings
3 from unittest import main
4
5 import eventlet
6 from eventlet import greenio
7 try:
8     from eventlet.green import ssl
9 except ImportError:
10     pass
11 from tests import (
12     LimitedTestCase, certificate_file, private_key_file, check_idle_cpu_usage,
13     skip_if_no_ssl
14 )
15
16
17 def listen_ssl_socket(address=('127.0.0.1', 0)):
18     sock = ssl.wrap_socket(
19         socket.socket(), private_key_file, certificate_file, server_side=True)
20     sock.bind(address)
21     sock.listen(50)
22
23     return sock
24
25
26 class SSLTest(LimitedTestCase):
27     def setUp(self):
28         # disabling socket.ssl warnings because we're testing it here
29         warnings.filterwarnings(
30             action='ignore',
31             message='.*socket.ssl.*',
32             category=DeprecationWarning)
33
34         super(SSLTest, self).setUp()
35
36     @skip_if_no_ssl
37     def test_duplex_response(self):
38         def serve(listener):
39             sock, addr = listener.accept()
40             sock.read(8192)
41             sock.write(b'response')
42
43         sock = listen_ssl_socket()
44
45         server_coro = eventlet.spawn(serve, sock)
46
47         client = ssl.wrap_socket(
48             eventlet.connect(('127.0.0.1', sock.getsockname()[1])))
49         client.write(b'line 1\r\nline 2\r\n\r\n')
50         self.assertEqual(client.read(8192), b'response')
51         server_coro.wait()
52
53     @skip_if_no_ssl
54     def test_ssl_close(self):
55         def serve(listener):
56             sock, addr = listener.accept()
57             sock.read(8192)
58             try:
59                 self.assertEqual(b"", sock.read(8192))
60             except greenio.SSL.ZeroReturnError:
61                 pass
62
63         sock = listen_ssl_socket()
64
65         server_coro = eventlet.spawn(serve, sock)
66
67         raw_client = eventlet.connect(('127.0.0.1', sock.getsockname()[1]))
68         client = ssl.wrap_socket(raw_client)
69         client.write(b'X')
70         greenio.shutdown_safe(client)
71         client.close()
72         server_coro.wait()
73
74     @skip_if_no_ssl
75     def test_ssl_connect(self):
76         def serve(listener):
77             sock, addr = listener.accept()
78             sock.read(8192)
79         sock = listen_ssl_socket()
80         server_coro = eventlet.spawn(serve, sock)
81
82         raw_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
83         ssl_client = ssl.wrap_socket(raw_client)
84         ssl_client.connect(('127.0.0.1', sock.getsockname()[1]))
85         ssl_client.write(b'abc')
86         greenio.shutdown_safe(ssl_client)
87         ssl_client.close()
88         server_coro.wait()
89
90     @skip_if_no_ssl
91     def test_ssl_unwrap(self):
92         def serve():
93             sock, addr = listener.accept()
94             self.assertEqual(sock.recv(6), b'before')
95             sock_ssl = ssl.wrap_socket(sock, private_key_file, certificate_file,
96                                        server_side=True)
97             sock_ssl.do_handshake()
98             self.assertEqual(sock_ssl.read(6), b'during')
99             sock2 = sock_ssl.unwrap()
100             self.assertEqual(sock2.recv(5), b'after')
101             sock2.close()
102
103         listener = eventlet.listen(('127.0.0.1', 0))
104         server_coro = eventlet.spawn(serve)
105         client = eventlet.connect((listener.getsockname()))
106         client.send(b'before')
107         client_ssl = ssl.wrap_socket(client)
108         client_ssl.do_handshake()
109         client_ssl.write(b'during')
110         client2 = client_ssl.unwrap()
111         client2.send(b'after')
112         server_coro.wait()
113
114     @skip_if_no_ssl
115     def test_sendall_cpu_usage(self):
116         """SSL socket.sendall() busy loop
117
118         https://bitbucket.org/eventlet/eventlet/issue/134/greenssl-performance-issues
119
120         Idea of this test is to check that GreenSSLSocket.sendall() does not busy loop
121         retrying .send() calls, but instead trampolines until socket is writeable.
122
123         BUFFER_SIZE and SENDALL_SIZE are magic numbers inferred through trial and error.
124         """
125         # Time limit resistant to busy loops
126         self.set_alarm(1)
127
128         stage_1 = eventlet.event.Event()
129         BUFFER_SIZE = 1000
130         SENDALL_SIZE = 100000
131
132         def serve(listener):
133             conn, _ = listener.accept()
134             conn.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, BUFFER_SIZE)
135             self.assertEqual(conn.read(8), b'request')
136             conn.write(b'response')
137
138             stage_1.wait()
139             conn.sendall(b'x' * SENDALL_SIZE)
140
141         server_sock = listen_ssl_socket()
142         server_coro = eventlet.spawn(serve, server_sock)
143
144         client_sock = eventlet.connect(server_sock.getsockname())
145         client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, BUFFER_SIZE)
146         client = ssl.wrap_socket(client_sock)
147         client.write(b'request')
148         self.assertEqual(client.read(8), b'response')
149         stage_1.send()
150
151         check_idle_cpu_usage(0.2, 0.1)
152         server_coro.kill()
153
154     @skip_if_no_ssl
155     def test_greensslobject(self):
156         def serve(listener):
157             sock, addr = listener.accept()
158             sock.write(b'content')
159             greenio.shutdown_safe(sock)
160             sock.close()
161         listener = listen_ssl_socket(('', 0))
162         eventlet.spawn(serve, listener)
163         client = ssl.wrap_socket(
164             eventlet.connect(('localhost', listener.getsockname()[1])))
165         self.assertEqual(client.read(1024), b'content')
166         self.assertEqual(client.read(1024), b'')
167
168     @skip_if_no_ssl
169     def test_regression_gh_17(self):
170         def serve(listener):
171             sock, addr = listener.accept()
172
173             # to simulate condition mentioned in GH-17
174             sock._sslobj = None
175             sock.sendall(b'some data')
176             greenio.shutdown_safe(sock)
177             sock.close()
178
179         listener = listen_ssl_socket(('', 0))
180         eventlet.spawn(serve, listener)
181         ssl.wrap_socket(eventlet.connect(('localhost', listener.getsockname()[1])))
182
183 if __name__ == '__main__':
184     main()