From e9f6614ea3b236851b536f6650cd6abe3f289dcb Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 7 Aug 2002 15:46:19 +0000 Subject: "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.) --- Lib/socket.py | 7 +++++-- Lib/test/test_socket.py | 41 +++++++++++++++++++++++++++++++++++------ 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__": -- cgit v0.12