tests: ssl: socket.sendall() busy loop when client is reading slowly

https://bitbucket.org/which_linden/eventlet/issue/134
This commit is contained in:
Sergey Shepelev
2013-01-11 17:00:37 +04:00
parent e90285a561
commit c8418a10e4

View File

@@ -1,10 +1,10 @@
from tests import LimitedTestCase, certificate_file, private_key_file from tests import LimitedTestCase, certificate_file, private_key_file, check_idle_cpu_usage
from tests import skip_if_no_ssl from tests import skip_if_no_ssl
from unittest import main from unittest import main
import eventlet import eventlet
from eventlet import util, coros, greenio from eventlet import util, greenio
import socket import socket
import os
def listen_ssl_socket(address=('127.0.0.1', 0)): def listen_ssl_socket(address=('127.0.0.1', 0)):
sock = util.wrap_ssl(socket.socket(), certificate_file, sock = util.wrap_ssl(socket.socket(), certificate_file,
@@ -13,7 +13,7 @@ def listen_ssl_socket(address=('127.0.0.1', 0)):
sock.listen(50) sock.listen(50)
return sock return sock
class SSLTest(LimitedTestCase): class SSLTest(LimitedTestCase):
@skip_if_no_ssl @skip_if_no_ssl
@@ -26,12 +26,12 @@ class SSLTest(LimitedTestCase):
sock = listen_ssl_socket() sock = listen_ssl_socket()
server_coro = eventlet.spawn(serve, sock) server_coro = eventlet.spawn(serve, sock)
client = util.wrap_ssl(eventlet.connect(('127.0.0.1', sock.getsockname()[1]))) client = util.wrap_ssl(eventlet.connect(('127.0.0.1', sock.getsockname()[1])))
client.write('line 1\r\nline 2\r\n\r\n') client.write('line 1\r\nline 2\r\n\r\n')
self.assertEquals(client.read(8192), 'response') self.assertEquals(client.read(8192), 'response')
server_coro.wait() server_coro.wait()
@skip_if_no_ssl @skip_if_no_ssl
def test_ssl_close(self): def test_ssl_close(self):
def serve(listener): def serve(listener):
@@ -41,18 +41,18 @@ class SSLTest(LimitedTestCase):
self.assertEquals("", sock.read(8192)) self.assertEquals("", sock.read(8192))
except greenio.SSL.ZeroReturnError: except greenio.SSL.ZeroReturnError:
pass pass
sock = listen_ssl_socket() sock = listen_ssl_socket()
server_coro = eventlet.spawn(serve, sock) server_coro = eventlet.spawn(serve, sock)
raw_client = eventlet.connect(('127.0.0.1', sock.getsockname()[1])) raw_client = eventlet.connect(('127.0.0.1', sock.getsockname()[1]))
client = util.wrap_ssl(raw_client) client = util.wrap_ssl(raw_client)
client.write('X') client.write('X')
greenio.shutdown_safe(client) greenio.shutdown_safe(client)
client.close() client.close()
server_coro.wait() server_coro.wait()
@skip_if_no_ssl @skip_if_no_ssl
def test_ssl_connect(self): def test_ssl_connect(self):
def serve(listener): def serve(listener):
@@ -60,7 +60,7 @@ class SSLTest(LimitedTestCase):
stuff = sock.read(8192) stuff = sock.read(8192)
sock = listen_ssl_socket() sock = listen_ssl_socket()
server_coro = eventlet.spawn(serve, sock) server_coro = eventlet.spawn(serve, sock)
raw_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) raw_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_client = util.wrap_ssl(raw_client) ssl_client = util.wrap_ssl(raw_client)
ssl_client.connect(('127.0.0.1', sock.getsockname()[1])) ssl_client.connect(('127.0.0.1', sock.getsockname()[1]))
@@ -93,6 +93,47 @@ class SSLTest(LimitedTestCase):
client2.send('after') client2.send('after')
server_coro.wait() server_coro.wait()
@skip_if_no_ssl
def test_sendall_cpu_usage(self):
"""SSL socket.sendall() busy loop
https://bitbucket.org/which_linden/eventlet/issue/134/greenssl-performance-issues
Idea of this test is to check that GreenSSLSocket.sendall() does not busy loop
retrying .send() calls, but instead trampolines until socket is writeable.
BUFFER_SIZE and SENDALL_SIZE are magic numbers inferred through trial and error.
"""
# Time limit resistant to busy loops
self.set_alarm(1)
stage_1 = eventlet.event.Event()
BUFFER_SIZE = 1000
SENDALL_SIZE = 100000
def serve(listener):
conn, _ = listener.accept()
conn.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, BUFFER_SIZE)
self.assertEqual(conn.read(8), 'request')
conn.write('response')
stage_1.wait()
conn.sendall('x' * SENDALL_SIZE)
server_sock = listen_ssl_socket()
server_coro = eventlet.spawn(serve, server_sock)
client_sock = eventlet.connect(server_sock.getsockname())
client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, BUFFER_SIZE)
client = util.wrap_ssl(client_sock)
client.write('request')
self.assertEqual(client.read(8), 'response')
stage_1.send()
check_idle_cpu_usage(0.2, 0.1)
server_coro.kill()
class SocketSSLTest(LimitedTestCase): class SocketSSLTest(LimitedTestCase):
@skip_if_no_ssl @skip_if_no_ssl
def test_greensslobject(self): def test_greensslobject(self):
@@ -114,6 +155,6 @@ class SocketSSLTest(LimitedTestCase):
self.assertEquals(client.read(1024), 'content') self.assertEquals(client.read(1024), 'content')
self.assertEquals(client.read(1024), '') self.assertEquals(client.read(1024), '')
if __name__ == '__main__': if __name__ == '__main__':
main() main()