"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.)
This commit is contained in:
parent
21f675826e
commit
e9f6614ea3
|
@ -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 = [ ]
|
||||
|
|
|
@ -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__":
|
||||
|
|
Loading…
Reference in New Issue