summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2002-08-07 15:46:19 (GMT)
committerGuido van Rossum <guido@python.org>2002-08-07 15:46:19 (GMT)
commite9f6614ea3b236851b536f6650cd6abe3f289dcb (patch)
tree43c161e4dea84de01a37a41f577f95dc0b21d085
parent21f675826e135695181e978c40605d3db92cc86b (diff)
downloadcpython-e9f6614ea3b236851b536f6650cd6abe3f289dcb.zip
cpython-e9f6614ea3b236851b536f6650cd6abe3f289dcb.tar.gz
cpython-e9f6614ea3b236851b536f6650cd6abe3f289dcb.tar.bz2
"Unbuffered" mode of class _fileobject wasn't actually unbuffered,
and this broke a Zope "pipelining" test which read multiple responses from the same connection (this attaches a new file object to the socket for each response). Added a test for this too. (I want to do some code cleanup too, but I thought I'd first fix the problem with as little code as possible, and add a unit test for this case. So that's what this checkin is about.)
-rw-r--r--Lib/socket.py7
-rw-r--r--Lib/test/test_socket.py41
2 files changed, 40 insertions, 8 deletions
diff --git a/Lib/socket.py b/Lib/socket.py
index 515d477..e59e6d9 100644
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -174,11 +174,14 @@ class _socketobject:
class _fileobject:
"""Implements a file object on top of a regular socket object."""
- def __init__(self, sock, mode='rb', bufsize=8192):
+ def __init__(self, sock, mode='rb', bufsize=-1):
self._sock = sock
self._mode = mode
if bufsize <= 0:
- bufsize = 512
+ if bufsize == 0:
+ bufsize = 1 # Unbuffered mode
+ else:
+ bufsize = 8192
self._rbufsize = bufsize
self._wbufsize = bufsize
self._rbuf = [ ]
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 737b431..ec3ed57 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -502,12 +502,14 @@ class NonBlockingTCPTests(ThreadedTCPSocketTest):
class FileObjectClassTestCase(SocketConnectedTest):
+ bufsize = -1 # Use default buffer size
+
def __init__(self, methodName='runTest'):
SocketConnectedTest.__init__(self, methodName=methodName)
def setUp(self):
SocketConnectedTest.setUp(self)
- self.serv_file = socket._fileobject(self.cli_conn, 'rb', 8192)
+ self.serv_file = self.cli_conn.makefile('rb', self.bufsize)
def tearDown(self):
self.serv_file.close()
@@ -516,7 +518,7 @@ class FileObjectClassTestCase(SocketConnectedTest):
def clientSetUp(self):
SocketConnectedTest.clientSetUp(self)
- self.cli_file = socket._fileobject(self.serv_conn, 'rb', 8192)
+ self.cli_file = self.serv_conn.makefile('wb')
def clientTearDown(self):
self.cli_file.close()
@@ -557,13 +559,40 @@ class FileObjectClassTestCase(SocketConnectedTest):
self.cli_file.write(MSG)
self.cli_file.flush()
+class UnbufferedFileObjectClassTestCase(FileObjectClassTestCase):
+
+ """Repeat the tests from FileObjectClassTestCase with bufsize==0.
+
+ In this case (and in this case only), it should be possible to
+ create a file object, read a line from it, create another file
+ object, read another line from it, without loss of data in the
+ first file object's buffer. Note that httplib relies on this
+ when reading multiple requests from the same socket."""
+
+ bufsize = 0 # Use unbuffered mode
+
+ def testUnbufferedReadline(self):
+ """Read a line, create a new file object, read another line with it."""
+ line = self.serv_file.readline() # first line
+ self.assertEqual(line, MSG) # first line
+ self.serv_file = self.cli_conn.makefile('rb', 0)
+ line = self.serv_file.readline() # second line
+ self.assertEqual(line, MSG) # second line
+
+ def _testUnbufferedReadline(self):
+ self.cli_file.write(MSG)
+ self.cli_file.write(MSG)
+ self.cli_file.flush()
+
+
def test_main():
suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(GeneralModuleTests))
- suite.addTest(unittest.makeSuite(BasicTCPTest))
- suite.addTest(unittest.makeSuite(BasicUDPTest))
- suite.addTest(unittest.makeSuite(NonBlockingTCPTests))
+ ##suite.addTest(unittest.makeSuite(GeneralModuleTests))
+ ##suite.addTest(unittest.makeSuite(BasicTCPTest))
+ ##suite.addTest(unittest.makeSuite(BasicUDPTest))
+ ##suite.addTest(unittest.makeSuite(NonBlockingTCPTests))
suite.addTest(unittest.makeSuite(FileObjectClassTestCase))
+ suite.addTest(unittest.makeSuite(UnbufferedFileObjectClassTestCase))
test_support.run_suite(suite)
if __name__ == "__main__":