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