Lib.test.test_select_new.py Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython Show documentation
Show all versions of jython Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
"""
AMAK: 20050515: This module is a brand new test_select module, which gives much wider coverage.
"""
import errno
import time
from test import test_support
import unittest
import socket
import select
SERVER_ADDRESS = ("localhost", 54321)
DATA_CHUNK_SIZE = 1000
DATA_CHUNK = "." * DATA_CHUNK_SIZE
#
# The timing of these tests depends on the how the unerlying OS socket library
# handles buffering. These values may need tweaking for different platforms
#
# The fundamental problem is that there is no reliable way to fill a socket with bytes
#
if test_support.is_jython:
SELECT_TIMEOUT = 0
else:
# zero select timeout fails these tests on cpython (on windows 2003 anyway)
SELECT_TIMEOUT = 0.001
READ_TIMEOUT = 5
class AsynchronousServer:
def __init__(self):
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setblocking(0)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind(SERVER_ADDRESS)
self.server_socket.listen(5)
try:
self.server_socket.accept()
except socket.error:
pass
def select_acceptable(self):
return select.select([self.server_socket], [self.server_socket], [], SELECT_TIMEOUT)[0]
def verify_acceptable(self):
start = time.time()
while True:
if self.select_acceptable():
return
elif (time.time() - start) > READ_TIMEOUT:
raise Exception('Server socket did not accept in time')
time.sleep(0.1)
def verify_not_acceptable(self):
assert not self.select_acceptable(), "Server socket should not be acceptable"
def accept(self):
self.verify_acceptable()
new_socket, address = self.server_socket.accept()
return AsynchronousHandler(new_socket)
def close(self):
self.server_socket.close()
class AsynchronousHandler:
def __init__(self, new_socket):
self.socket = new_socket
self.socket.setblocking(0)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def write(self):
"""
Writes on this channel until select no longer reports it as writable.
Returns the number of bytes written
"""
total_bytes = 0
while 1:
try:
if self.select_writable():
bytes_sent = self.socket.send(DATA_CHUNK)
total_bytes += bytes_sent
else:
return total_bytes
except socket.error, se:
if se.value == 10035:
continue
raise se
def read(self, expected):
"""
Reads expected bytes from this socket
An Exception is raised if expected bytes aren't read before READ_TIMEOUT
is reached.
"""
results = ""
start = time.time()
while 1:
if self.select_readable():
recvd_bytes = self.socket.recv(expected - len(results))
if len(recvd_bytes):
results += recvd_bytes
if len(results) == expected:
return results
else:
stop = time.time()
if (stop - start) > READ_TIMEOUT:
raise Exception("Got %d bytes but %d bytes were written." %
(len(results), expected))
def select_readable(self):
return select.select([self.socket], [], [], SELECT_TIMEOUT)[0]
def verify_readable(self):
assert self.select_readable(), "Socket should be ready for reading"
def verify_not_readable(self):
assert not self.select_readable(), "Socket should not be ready for reading"
def select_writable(self):
return select.select([], [self.socket], [], SELECT_TIMEOUT)[1]
def verify_writable(self):
assert self.select_writable(), "Socket should be ready for writing"
def verify_not_writable(self):
assert not self.select_writable(), "Socket should not be ready for writing"
def verify_only_writable(self):
self.verify_writable()
self.verify_not_readable()
def close(self):
self.socket.close()
class AsynchronousClient(AsynchronousHandler):
def __init__(self):
AsynchronousHandler.__init__(self, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
self.connected = 0
def start_connect(self):
result = self.socket.connect_ex(SERVER_ADDRESS)
if result == errno.EISCONN:
self.connected = 1
else:
assert result == errno.EINPROGRESS
def finish_connect(self):
if self.connected:
return
start = time.time()
while True:
self.start_connect()
if self.connected:
break
elif (time.time() - start) > READ_TIMEOUT:
raise Exception('Client socket incomplete connect')
time.sleep(0.1)
class TestSelectOnAccept(unittest.TestCase):
def setUp(self):
self.server = AsynchronousServer()
self.client = AsynchronousClient()
self.handler = None
def testSelectOnAccept(self):
self.server.verify_not_acceptable()
self.client.start_connect()
self.server.verify_acceptable()
self.handler = self.server.accept()
self.client.finish_connect()
self.server.verify_not_acceptable()
def tearDown(self):
self.client.close()
if self.handler:
self.handler.close()
self.server.close()
class TestSelect(unittest.TestCase):
def setUp(self):
self.server = AsynchronousServer()
self.client = AsynchronousClient()
self.client.start_connect()
self.handler = self.server.accept()
self.client.finish_connect()
def tearDown(self):
self.client.close()
self.handler.close()
self.server.close()
def testClientOut(self):
self.client.verify_only_writable()
self.handler.verify_only_writable()
written = self.client.write()
self.handler.verify_readable()
self.handler.read(written/2)
self.handler.verify_readable()
self.handler.read(written/2)
self.handler.verify_not_readable()
def testHandlerOut(self):
written = self.handler.write()
self.client.verify_readable()
self.client.read(written/2)
self.client.verify_readable()
self.client.read(written/2)
self.client.verify_not_readable()
def testBothOut(self):
client_written = self.client.write()
handler_written = self.handler.write()
self.client.verify_readable()
self.handler.verify_readable()
self.client.read(handler_written/2)
self.handler.read(client_written/2)
self.client.verify_readable()
self.handler.verify_readable()
self.client.read(handler_written/2)
self.handler.read(client_written/2)
self.client.verify_only_writable()
self.handler.verify_only_writable()
def test_main():
test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()