New version from Mike Verdone (sat in my inbox since 2/27).
I cleaned up whitespace but otherwise didn't change it.
This will need work to reflect the tentative decision to drop nonblocking I/O
support from the buffering layers.
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index 7384999..1be1b71 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -5,10 +5,10 @@
import io
-
-class MockReadIO(io.RawIOBase):
- def __init__(self, readStack):
+class MockIO(io.RawIOBase):
+ def __init__(self, readStack=()):
self._readStack = list(readStack)
+ self._writeStack = []
def read(self, n=None):
try:
@@ -16,27 +16,41 @@
except:
return io.EOF
+ def write(self, b):
+ self._writeStack.append(b)
+ return len(b)
+
+ def writable(self):
+ return True
+
def fileno(self):
return 42
def readable(self):
return True
-
-class MockWriteIO(io.RawIOBase):
- def __init__(self):
- self._writeStack = []
-
- def write(self, b):
- self._writeStack.append(b)
- return len(b)
-
- def writeable(self):
+ def seekable(self):
return True
- def fileno(self):
+ def seek(self, pos, whence):
+ pass
+
+ def tell(self):
return 42
+class MockNonBlockWriterIO(io.RawIOBase):
+ def __init__(self, blockingScript):
+ self.bs = list(blockingScript)
+ self._write_stack = []
+ def write(self, b):
+ self._write_stack.append(b)
+ n = self.bs.pop(0)
+ if (n < 0):
+ raise io.BlockingIO(0, "test blocking", -n)
+ else:
+ return n
+ def writable(self):
+ return True
class IOTest(unittest.TestCase):
@@ -90,9 +104,7 @@
f = io.BytesIO(data)
self.read_ops(f)
-
class BytesIOTest(unittest.TestCase):
-
def testInit(self):
buf = b"1234567890"
bytesIo = io.BytesIO(buf)
@@ -134,44 +146,51 @@
bytesIo.seek(10000)
self.assertEquals(10000, bytesIo.tell())
-
class BufferedReaderTest(unittest.TestCase):
-
def testRead(self):
- rawIo = MockReadIO((b"abc", b"d", b"efg"))
+ rawIo = MockIO((b"abc", b"d", b"efg"))
bufIo = io.BufferedReader(rawIo)
self.assertEquals(b"abcdef", bufIo.read(6))
+ def testReadNonBlocking(self):
+ # Inject some None's in there to simulate EWOULDBLOCK
+ rawIo = MockIO((b"abc", b"d", None, b"efg", None, None))
+ bufIo = io.BufferedReader(rawIo)
+
+ self.assertEquals(b"abcd", bufIo.read(6))
+ self.assertEquals(b"e", bufIo.read(1))
+ self.assertEquals(b"fg", bufIo.read())
+ self.assert_(None is bufIo.read())
+ self.assertEquals(io.EOF, bufIo.read())
+
def testReadToEof(self):
- rawIo = MockReadIO((b"abc", b"d", b"efg"))
+ rawIo = MockIO((b"abc", b"d", b"efg"))
bufIo = io.BufferedReader(rawIo)
self.assertEquals(b"abcdefg", bufIo.read(9000))
def testReadNoArgs(self):
- rawIo = MockReadIO((b"abc", b"d", b"efg"))
+ rawIo = MockIO((b"abc", b"d", b"efg"))
bufIo = io.BufferedReader(rawIo)
self.assertEquals(b"abcdefg", bufIo.read())
def testFileno(self):
- rawIo = MockReadIO((b"abc", b"d", b"efg"))
+ rawIo = MockIO((b"abc", b"d", b"efg"))
bufIo = io.BufferedReader(rawIo)
self.assertEquals(42, bufIo.fileno())
def testFilenoNoFileno(self):
- # TODO will we always have fileno() function? If so, kill
+ # XXX will we always have fileno() function? If so, kill
# this test. Else, write it.
pass
-
class BufferedWriterTest(unittest.TestCase):
-
def testWrite(self):
# Write to the buffered IO but don't overflow the buffer.
- writer = MockWriteIO()
+ writer = MockIO()
bufIo = io.BufferedWriter(writer, 8)
bufIo.write(b"abc")
@@ -179,7 +198,7 @@
self.assertFalse(writer._writeStack)
def testWriteOverflow(self):
- writer = MockWriteIO()
+ writer = MockIO()
bufIo = io.BufferedWriter(writer, 8)
bufIo.write(b"abc")
@@ -187,8 +206,33 @@
self.assertEquals(b"abcdefghijkl", writer._writeStack[0])
+ def testWriteNonBlocking(self):
+ raw = MockNonBlockWriterIO((9, 2, 22, -6, 10, 12, 12))
+ bufIo = io.BufferedWriter(raw, 8, 16)
+
+ bufIo.write(b"asdf")
+ bufIo.write(b"asdfa")
+ self.assertEquals(b"asdfasdfa", raw._write_stack[0])
+
+ bufIo.write(b"asdfasdfasdf")
+ self.assertEquals(b"asdfasdfasdf", raw._write_stack[1])
+ bufIo.write(b"asdfasdfasdf")
+ self.assertEquals(b"dfasdfasdf", raw._write_stack[2])
+ self.assertEquals(b"asdfasdfasdf", raw._write_stack[3])
+
+ bufIo.write(b"asdfasdfasdf")
+
+ # XXX I don't like this test. It relies too heavily on how the algorithm
+ # actually works, which we might change. Refactor later.
+
+ def testFileno(self):
+ rawIo = MockIO((b"abc", b"d", b"efg"))
+ bufIo = io.BufferedWriter(rawIo)
+
+ self.assertEquals(42, bufIo.fileno())
+
def testFlush(self):
- writer = MockWriteIO()
+ writer = MockIO()
bufIo = io.BufferedWriter(writer, 8)
bufIo.write(b"abc")
@@ -196,11 +240,51 @@
self.assertEquals(b"abc", writer._writeStack[0])
-# TODO. Tests for open()
+class BufferedRWPairTest(unittest.TestCase):
+ def testRWPair(self):
+ r = MockIO(())
+ w = MockIO()
+ pair = io.BufferedRWPair(r, w)
+
+ # XXX need implementation
+
+class BufferedRandom(unittest.TestCase):
+ def testReadAndWrite(self):
+ raw = MockIO((b"asdf", b"ghjk"))
+ rw = io.BufferedRandom(raw, 8, 12)
+
+ self.assertEqual(b"as", rw.read(2))
+ rw.write(b"ddd")
+ rw.write(b"eee")
+ self.assertFalse(raw._writeStack) # Buffer writes
+ self.assertEqual(b"ghjk", rw.read()) # This read forces write flush
+ self.assertEquals(b"dddeee", raw._writeStack[0])
+
+ def testSeekAndTell(self):
+ raw = io.BytesIO(b"asdfghjkl")
+ rw = io.BufferedRandom(raw)
+
+ self.assertEquals(b"as", rw.read(2))
+ self.assertEquals(2, rw.tell())
+ rw.seek(0, 0)
+ self.assertEquals(b"asdf", rw.read(4))
+
+ rw.write(b"asdf")
+ rw.seek(0, 0)
+ self.assertEquals(b"asdfasdfl", rw.read())
+ self.assertEquals(9, rw.tell())
+ rw.seek(-4, 2)
+ self.assertEquals(5, rw.tell())
+ rw.seek(2, 1)
+ self.assertEquals(7, rw.tell())
+ self.assertEquals(b"fl", rw.read(11))
+
+# XXX Tests for open()
def test_main():
test_support.run_unittest(IOTest, BytesIOTest, BufferedReaderTest,
- BufferedWriterTest)
+ BufferedWriterTest, BufferedRWPairTest,
+ BufferedRandom)
if __name__ == "__main__":
test_main()