Files
deb-python-eventlet/tests/greenio_test.py

266 lines
9.6 KiB
Python

from tests import skipped, LimitedTestCase, skip_with_libevent, TestIsTakingTooLong
from unittest import main
from eventlet import api, util, coros, proc, greenio
import os
import socket
import sys
def bufsized(sock, size=1):
""" Resize both send and receive buffers on a socket.
Useful for testing trampoline. Returns the socket.
>>> import socket
>>> sock = bufsized(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
"""
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, size)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, size)
return sock
class TestGreenIo(LimitedTestCase):
def test_close_with_makefile(self):
def accept_close_early(listener):
# verify that the makefile and the socket are truly independent
# by closing the socket prior to using the made file
try:
conn, addr = listener.accept()
fd = conn.makeGreenFile()
conn.close()
fd.write('hello\n')
fd.close()
self.assertRaises(socket.error, fd.write, 'a')
self.assertRaises(socket.error, conn.send, 'b')
finally:
listener.close()
def accept_close_late(listener):
# verify that the makefile and the socket are truly independent
# by closing the made file and then sending a character
try:
conn, addr = listener.accept()
fd = conn.makeGreenFile()
fd.write('hello')
fd.close()
conn.send('\n')
conn.close()
self.assertRaises(socket.error, fd.write, 'a')
self.assertRaises(socket.error, conn.send, 'b')
finally:
listener.close()
def did_it_work(server):
client = api.connect_tcp(('127.0.0.1', server.getsockname()[1]))
fd = client.makeGreenFile()
client.close()
assert fd.readline() == 'hello\n'
assert fd.read() == ''
fd.close()
server = api.tcp_listener(('0.0.0.0', 0))
killer = coros.execute(accept_close_early, server)
did_it_work(server)
killer.wait()
server = api.tcp_listener(('0.0.0.0', 0))
killer = coros.execute(accept_close_late, server)
did_it_work(server)
killer.wait()
def test_del_closes_socket(self):
def accept_once(listener):
# delete/overwrite the original conn
# object, only keeping the file object around
# closing the file object should close everything
try:
conn, addr = listener.accept()
conn = conn.makeGreenFile()
conn.write('hello\n')
conn.close()
self.assertRaises(socket.error, conn.write, 'a')
finally:
listener.close()
server = api.tcp_listener(('0.0.0.0', 0))
killer = coros.execute(accept_once, server)
client = api.connect_tcp(('127.0.0.1', server.getsockname()[1]))
fd = client.makeGreenFile()
client.close()
assert fd.read() == 'hello\n'
assert fd.read() == ''
killer.wait()
def test_full_duplex(self):
large_data = '*' * 10
listener = bufsized(api.tcp_listener(('127.0.0.1', 0)))
def send_large(sock):
sock.sendall(large_data)
def read_large(sock):
result = sock.recv(len(large_data))
expected = 'hello world'
while len(result) < len(large_data):
result += sock.recv(len(large_data))
self.assertEquals(result, large_data)
def server():
(sock, addr) = listener.accept()
sock = bufsized(sock)
send_large_coro = coros.execute(send_large, sock)
api.sleep(0)
result = sock.recv(10)
expected = 'hello world'
while len(result) < len(expected):
result += sock.recv(10)
self.assertEquals(result, expected)
send_large_coro.wait()
server_evt = coros.execute(server)
client = bufsized(api.connect_tcp(('127.0.0.1',
listener.getsockname()[1])))
large_evt = coros.execute(read_large, client)
api.sleep(0)
client.sendall('hello world')
server_evt.wait()
large_evt.wait()
client.close()
def test_sendall(self):
# test adapted from Brian Brunswick's email
# it may legitimately take a while, but will eventually complete
self.timer.cancel()
second_bytes = 10
def test_sendall_impl(many_bytes):
bufsize = max(many_bytes/15, 2)
def sender(listener):
(sock, addr) = listener.accept()
sock = bufsized(sock, size=bufsize)
sock.sendall('x'*many_bytes)
sock.sendall('y'*second_bytes)
listener = api.tcp_listener(("", 0))
sender_coro = proc.spawn(sender, listener)
client = bufsized(api.connect_tcp(('localhost',
listener.getsockname()[1])),
size=bufsize)
total = 0
while total < many_bytes:
data = client.recv(min(many_bytes - total, many_bytes/10))
if data == '':
break
total += len(data)
total2 = 0
while total < second_bytes:
data = client.recv(second_bytes)
if data == '':
break
total2 += len(data)
sender_coro.wait()
client.close()
for bytes in (1000, 10000, 100000, 1000000):
test_sendall_impl(bytes)
@skip_with_libevent
def test_multiple_readers(self):
recvsize = 1
sendsize = 10
if sys.version_info < (2,5):
# 2.4 doesn't implement buffer sizing exactly the way we
# expect so we have to send more data to ensure that we
# actually call trampoline() multiple times during this
# function
recvsize = 4000
sendsize = 40000
# and reset the timer because we're going to be taking
# longer to send all this extra data
self.timer.cancel()
self.timer = api.exc_after(10, TestIsTakingTooLong(10))
# test that we can have multiple coroutines reading
# from the same fd. We make no guarantees about which one gets which
# bytes, but they should both get at least some
def reader(sock, results):
while True:
data = sock.recv(recvsize)
if data == '':
break
results.append(data)
results1 = []
results2 = []
listener = api.tcp_listener(('127.0.0.1', 0))
def server():
(sock, addr) = listener.accept()
sock = bufsized(sock)
try:
c1 = proc.spawn(reader, sock, results1)
c2 = proc.spawn(reader, sock, results2)
c1.wait()
c2.wait()
finally:
c1.kill()
c2.kill()
sock.close()
server_coro = proc.spawn(server)
client = bufsized(api.connect_tcp(('127.0.0.1',
listener.getsockname()[1])))
client.sendall('*' * sendsize)
client.close()
server_coro.wait()
listener.close()
print len(results1), len(results2)
self.assert_(len(results1) > 0)
self.assert_(len(results2) > 0)
def test_wrap_socket(self):
try:
import ssl
except ImportError:
pass # pre-2.6
else:
sock = api.tcp_listener(('127.0.0.1', 0))
ssl_sock = ssl.wrap_socket(sock)
class SSLTest(LimitedTestCase):
def setUp(self):
super(SSLTest, self).setUp()
self.certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
self.private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
def test_duplex_response(self):
def serve(listener):
sock, addr = listener.accept()
stuff = sock.read(8192)
sock.write('response')
sock = api.ssl_listener(('127.0.0.1', 0), self.certificate_file, self.private_key_file)
server_coro = coros.execute(serve, sock)
client = util.wrap_ssl(api.connect_tcp(('127.0.0.1', sock.getsockname()[1])))
client.write('line 1\r\nline 2\r\n\r\n')
self.assertEquals(client.read(8192), 'response')
server_coro.wait()
def test_greensslobject(self):
def serve(listener):
sock, addr = listener.accept()
sock.write('content')
sock.shutdown()
sock.close()
listener = api.ssl_listener(('', 0),
self.certificate_file,
self.private_key_file)
killer = api.spawn(serve, listener)
client = util.wrap_ssl(api.connect_tcp(('localhost', listener.getsockname()[1])))
client = greenio.GreenSSLObject(client)
self.assertEquals(client.read(1024), 'content')
self.assertEquals(client.read(1024), '')
if __name__ == '__main__':
main()