/External.LCA_RESTRICTED/Languages/CPython/27/Lib/test/test_io.py
http://github.com/IronLanguages/main · Python · 2782 lines · 2269 code · 317 blank · 196 comment · 207 complexity · 8639be738ac6943e6cc6b971842110ff MD5 · raw file
Large files are truncated click here to view the full file
- """Unit tests for the io module."""
- # Tests of io are scattered over the test suite:
- # * test_bufio - tests file buffering
- # * test_memoryio - tests BytesIO and StringIO
- # * test_fileio - tests FileIO
- # * test_file - tests the file interface
- # * test_io - tests everything else in the io module
- # * test_univnewlines - tests universal newline support
- # * test_largefile - tests operations on a file greater than 2**32 bytes
- # (only enabled with -ulargefile)
- ################################################################################
- # ATTENTION TEST WRITERS!!!
- ################################################################################
- # When writing tests for io, it's important to test both the C and Python
- # implementations. This is usually done by writing a base test that refers to
- # the type it is testing as a attribute. Then it provides custom subclasses to
- # test both implementations. This file has lots of examples.
- ################################################################################
- from __future__ import print_function
- from __future__ import unicode_literals
- import os
- import sys
- import time
- import array
- import random
- import unittest
- import weakref
- import abc
- import signal
- import errno
- from itertools import cycle, count
- from collections import deque
- from test import test_support as support
- import codecs
- import io # C implementation of io
- import _pyio as pyio # Python implementation of io
- try:
- import threading
- except ImportError:
- threading = None
- __metaclass__ = type
- bytes = support.py3k_bytes
- def _default_chunk_size():
- """Get the default TextIOWrapper chunk size"""
- with io.open(__file__, "r", encoding="latin1") as f:
- return f._CHUNK_SIZE
- class MockRawIOWithoutRead:
- """A RawIO implementation without read(), so as to exercise the default
- RawIO.read() which calls readinto()."""
- def __init__(self, read_stack=()):
- self._read_stack = list(read_stack)
- self._write_stack = []
- self._reads = 0
- self._extraneous_reads = 0
- def write(self, b):
- self._write_stack.append(bytes(b))
- return len(b)
- def writable(self):
- return True
- def fileno(self):
- return 42
- def readable(self):
- return True
- def seekable(self):
- return True
- def seek(self, pos, whence):
- return 0 # wrong but we gotta return something
- def tell(self):
- return 0 # same comment as above
- def readinto(self, buf):
- self._reads += 1
- max_len = len(buf)
- try:
- data = self._read_stack[0]
- except IndexError:
- self._extraneous_reads += 1
- return 0
- if data is None:
- del self._read_stack[0]
- return None
- n = len(data)
- if len(data) <= max_len:
- del self._read_stack[0]
- buf[:n] = data
- return n
- else:
- buf[:] = data[:max_len]
- self._read_stack[0] = data[max_len:]
- return max_len
- def truncate(self, pos=None):
- return pos
- class CMockRawIOWithoutRead(MockRawIOWithoutRead, io.RawIOBase):
- pass
- class PyMockRawIOWithoutRead(MockRawIOWithoutRead, pyio.RawIOBase):
- pass
- class MockRawIO(MockRawIOWithoutRead):
- def read(self, n=None):
- self._reads += 1
- try:
- return self._read_stack.pop(0)
- except:
- self._extraneous_reads += 1
- return b""
- class CMockRawIO(MockRawIO, io.RawIOBase):
- pass
- class PyMockRawIO(MockRawIO, pyio.RawIOBase):
- pass
- class MisbehavedRawIO(MockRawIO):
- def write(self, b):
- return MockRawIO.write(self, b) * 2
- def read(self, n=None):
- return MockRawIO.read(self, n) * 2
- def seek(self, pos, whence):
- return -123
- def tell(self):
- return -456
- def readinto(self, buf):
- MockRawIO.readinto(self, buf)
- return len(buf) * 5
- class CMisbehavedRawIO(MisbehavedRawIO, io.RawIOBase):
- pass
- class PyMisbehavedRawIO(MisbehavedRawIO, pyio.RawIOBase):
- pass
- class CloseFailureIO(MockRawIO):
- closed = 0
- def close(self):
- if not self.closed:
- self.closed = 1
- raise IOError
- class CCloseFailureIO(CloseFailureIO, io.RawIOBase):
- pass
- class PyCloseFailureIO(CloseFailureIO, pyio.RawIOBase):
- pass
- class MockFileIO:
- def __init__(self, data):
- self.read_history = []
- super(MockFileIO, self).__init__(data)
- def read(self, n=None):
- res = super(MockFileIO, self).read(n)
- self.read_history.append(None if res is None else len(res))
- return res
- def readinto(self, b):
- res = super(MockFileIO, self).readinto(b)
- self.read_history.append(res)
- return res
- class CMockFileIO(MockFileIO, io.BytesIO):
- pass
- class PyMockFileIO(MockFileIO, pyio.BytesIO):
- pass
- class MockNonBlockWriterIO:
- def __init__(self):
- self._write_stack = []
- self._blocker_char = None
- def pop_written(self):
- s = b"".join(self._write_stack)
- self._write_stack[:] = []
- return s
- def block_on(self, char):
- """Block when a given char is encountered."""
- self._blocker_char = char
- def readable(self):
- return True
- def seekable(self):
- return True
- def writable(self):
- return True
- def write(self, b):
- b = bytes(b)
- n = -1
- if self._blocker_char:
- try:
- n = b.index(self._blocker_char)
- except ValueError:
- pass
- else:
- self._blocker_char = None
- self._write_stack.append(b[:n])
- raise self.BlockingIOError(0, "test blocking", n)
- self._write_stack.append(b)
- return len(b)
- class CMockNonBlockWriterIO(MockNonBlockWriterIO, io.RawIOBase):
- BlockingIOError = io.BlockingIOError
- class PyMockNonBlockWriterIO(MockNonBlockWriterIO, pyio.RawIOBase):
- BlockingIOError = pyio.BlockingIOError
- class IOTest(unittest.TestCase):
- def setUp(self):
- support.unlink(support.TESTFN)
- def tearDown(self):
- support.unlink(support.TESTFN)
- def write_ops(self, f):
- self.assertEqual(f.write(b"blah."), 5)
- f.truncate(0)
- self.assertEqual(f.tell(), 5)
- f.seek(0)
- self.assertEqual(f.write(b"blah."), 5)
- self.assertEqual(f.seek(0), 0)
- self.assertEqual(f.write(b"Hello."), 6)
- self.assertEqual(f.tell(), 6)
- self.assertEqual(f.seek(-1, 1), 5)
- self.assertEqual(f.tell(), 5)
- self.assertEqual(f.write(bytearray(b" world\n\n\n")), 9)
- self.assertEqual(f.seek(0), 0)
- self.assertEqual(f.write(b"h"), 1)
- self.assertEqual(f.seek(-1, 2), 13)
- self.assertEqual(f.tell(), 13)
- self.assertEqual(f.truncate(12), 12)
- self.assertEqual(f.tell(), 13)
- self.assertRaises(TypeError, f.seek, 0.0)
- def read_ops(self, f, buffered=False):
- data = f.read(5)
- self.assertEqual(data, b"hello")
- data = bytearray(data)
- self.assertEqual(f.readinto(data), 5)
- self.assertEqual(data, b" worl")
- self.assertEqual(f.readinto(data), 2)
- self.assertEqual(len(data), 5)
- self.assertEqual(data[:2], b"d\n")
- self.assertEqual(f.seek(0), 0)
- self.assertEqual(f.read(20), b"hello world\n")
- self.assertEqual(f.read(1), b"")
- self.assertEqual(f.readinto(bytearray(b"x")), 0)
- self.assertEqual(f.seek(-6, 2), 6)
- self.assertEqual(f.read(5), b"world")
- self.assertEqual(f.read(0), b"")
- self.assertEqual(f.readinto(bytearray()), 0)
- self.assertEqual(f.seek(-6, 1), 5)
- self.assertEqual(f.read(5), b" worl")
- self.assertEqual(f.tell(), 10)
- self.assertRaises(TypeError, f.seek, 0.0)
- if buffered:
- f.seek(0)
- self.assertEqual(f.read(), b"hello world\n")
- f.seek(6)
- self.assertEqual(f.read(), b"world\n")
- self.assertEqual(f.read(), b"")
- LARGE = 2**31
- def large_file_ops(self, f):
- assert f.readable()
- assert f.writable()
- self.assertEqual(f.seek(self.LARGE), self.LARGE)
- self.assertEqual(f.tell(), self.LARGE)
- self.assertEqual(f.write(b"xxx"), 3)
- self.assertEqual(f.tell(), self.LARGE + 3)
- self.assertEqual(f.seek(-1, 1), self.LARGE + 2)
- self.assertEqual(f.truncate(), self.LARGE + 2)
- self.assertEqual(f.tell(), self.LARGE + 2)
- self.assertEqual(f.seek(0, 2), self.LARGE + 2)
- self.assertEqual(f.truncate(self.LARGE + 1), self.LARGE + 1)
- self.assertEqual(f.tell(), self.LARGE + 2)
- self.assertEqual(f.seek(0, 2), self.LARGE + 1)
- self.assertEqual(f.seek(-1, 2), self.LARGE)
- self.assertEqual(f.read(2), b"x")
- def test_invalid_operations(self):
- # Try writing on a file opened in read mode and vice-versa.
- for mode in ("w", "wb"):
- with self.open(support.TESTFN, mode) as fp:
- self.assertRaises(IOError, fp.read)
- self.assertRaises(IOError, fp.readline)
- with self.open(support.TESTFN, "rb") as fp:
- self.assertRaises(IOError, fp.write, b"blah")
- self.assertRaises(IOError, fp.writelines, [b"blah\n"])
- with self.open(support.TESTFN, "r") as fp:
- self.assertRaises(IOError, fp.write, "blah")
- self.assertRaises(IOError, fp.writelines, ["blah\n"])
- def test_raw_file_io(self):
- with self.open(support.TESTFN, "wb", buffering=0) as f:
- self.assertEqual(f.readable(), False)
- self.assertEqual(f.writable(), True)
- self.assertEqual(f.seekable(), True)
- self.write_ops(f)
- with self.open(support.TESTFN, "rb", buffering=0) as f:
- self.assertEqual(f.readable(), True)
- self.assertEqual(f.writable(), False)
- self.assertEqual(f.seekable(), True)
- self.read_ops(f)
- def test_buffered_file_io(self):
- with self.open(support.TESTFN, "wb") as f:
- self.assertEqual(f.readable(), False)
- self.assertEqual(f.writable(), True)
- self.assertEqual(f.seekable(), True)
- self.write_ops(f)
- with self.open(support.TESTFN, "rb") as f:
- self.assertEqual(f.readable(), True)
- self.assertEqual(f.writable(), False)
- self.assertEqual(f.seekable(), True)
- self.read_ops(f, True)
- def test_readline(self):
- with self.open(support.TESTFN, "wb") as f:
- f.write(b"abc\ndef\nxyzzy\nfoo\x00bar\nanother line")
- with self.open(support.TESTFN, "rb") as f:
- self.assertEqual(f.readline(), b"abc\n")
- self.assertEqual(f.readline(10), b"def\n")
- self.assertEqual(f.readline(2), b"xy")
- self.assertEqual(f.readline(4), b"zzy\n")
- self.assertEqual(f.readline(), b"foo\x00bar\n")
- self.assertEqual(f.readline(None), b"another line")
- self.assertRaises(TypeError, f.readline, 5.3)
- with self.open(support.TESTFN, "r") as f:
- self.assertRaises(TypeError, f.readline, 5.3)
- def test_raw_bytes_io(self):
- f = self.BytesIO()
- self.write_ops(f)
- data = f.getvalue()
- self.assertEqual(data, b"hello world\n")
- f = self.BytesIO(data)
- self.read_ops(f, True)
- def test_large_file_ops(self):
- # On Windows and Mac OSX this test comsumes large resources; It takes
- # a long time to build the >2GB file and takes >2GB of disk space
- # therefore the resource must be enabled to run this test.
- if sys.platform[:3] == 'win' or sys.platform == 'darwin':
- if not support.is_resource_enabled("largefile"):
- print("\nTesting large file ops skipped on %s." % sys.platform,
- file=sys.stderr)
- print("It requires %d bytes and a long time." % self.LARGE,
- file=sys.stderr)
- print("Use 'regrtest.py -u largefile test_io' to run it.",
- file=sys.stderr)
- return
- with self.open(support.TESTFN, "w+b", 0) as f:
- self.large_file_ops(f)
- with self.open(support.TESTFN, "w+b") as f:
- self.large_file_ops(f)
- def test_with_open(self):
- for bufsize in (0, 1, 100):
- f = None
- with self.open(support.TESTFN, "wb", bufsize) as f:
- f.write(b"xxx")
- self.assertEqual(f.closed, True)
- f = None
- try:
- with self.open(support.TESTFN, "wb", bufsize) as f:
- 1 // 0
- except ZeroDivisionError:
- self.assertEqual(f.closed, True)
- else:
- self.fail("1 // 0 didn't raise an exception")
- # issue 5008
- def test_append_mode_tell(self):
- with self.open(support.TESTFN, "wb") as f:
- f.write(b"xxx")
- with self.open(support.TESTFN, "ab", buffering=0) as f:
- self.assertEqual(f.tell(), 3)
- with self.open(support.TESTFN, "ab") as f:
- self.assertEqual(f.tell(), 3)
- with self.open(support.TESTFN, "a") as f:
- self.assertTrue(f.tell() > 0)
- def test_destructor(self):
- record = []
- class MyFileIO(self.FileIO):
- def __del__(self):
- record.append(1)
- try:
- f = super(MyFileIO, self).__del__
- except AttributeError:
- pass
- else:
- f()
- def close(self):
- record.append(2)
- super(MyFileIO, self).close()
- def flush(self):
- record.append(3)
- super(MyFileIO, self).flush()
- f = MyFileIO(support.TESTFN, "wb")
- f.write(b"xxx")
- del f
- support.gc_collect()
- self.assertEqual(record, [1, 2, 3])
- with self.open(support.TESTFN, "rb") as f:
- self.assertEqual(f.read(), b"xxx")
- def _check_base_destructor(self, base):
- record = []
- class MyIO(base):
- def __init__(self):
- # This exercises the availability of attributes on object
- # destruction.
- # (in the C version, close() is called by the tp_dealloc
- # function, not by __del__)
- self.on_del = 1
- self.on_close = 2
- self.on_flush = 3
- def __del__(self):
- record.append(self.on_del)
- try:
- f = super(MyIO, self).__del__
- except AttributeError:
- pass
- else:
- f()
- def close(self):
- record.append(self.on_close)
- super(MyIO, self).close()
- def flush(self):
- record.append(self.on_flush)
- super(MyIO, self).flush()
- f = MyIO()
- del f
- support.gc_collect()
- self.assertEqual(record, [1, 2, 3])
- def test_IOBase_destructor(self):
- self._check_base_destructor(self.IOBase)
- def test_RawIOBase_destructor(self):
- self._check_base_destructor(self.RawIOBase)
- def test_BufferedIOBase_destructor(self):
- self._check_base_destructor(self.BufferedIOBase)
- def test_TextIOBase_destructor(self):
- self._check_base_destructor(self.TextIOBase)
- def test_close_flushes(self):
- with self.open(support.TESTFN, "wb") as f:
- f.write(b"xxx")
- with self.open(support.TESTFN, "rb") as f:
- self.assertEqual(f.read(), b"xxx")
- def test_array_writes(self):
- a = array.array(b'i', range(10))
- n = len(a.tostring())
- with self.open(support.TESTFN, "wb", 0) as f:
- self.assertEqual(f.write(a), n)
- with self.open(support.TESTFN, "wb") as f:
- self.assertEqual(f.write(a), n)
- def test_closefd(self):
- self.assertRaises(ValueError, self.open, support.TESTFN, 'w',
- closefd=False)
- def test_read_closed(self):
- with self.open(support.TESTFN, "w") as f:
- f.write("egg\n")
- with self.open(support.TESTFN, "r") as f:
- file = self.open(f.fileno(), "r", closefd=False)
- self.assertEqual(file.read(), "egg\n")
- file.seek(0)
- file.close()
- self.assertRaises(ValueError, file.read)
- def test_no_closefd_with_filename(self):
- # can't use closefd in combination with a file name
- self.assertRaises(ValueError, self.open, support.TESTFN, "r", closefd=False)
- def test_closefd_attr(self):
- with self.open(support.TESTFN, "wb") as f:
- f.write(b"egg\n")
- with self.open(support.TESTFN, "r") as f:
- self.assertEqual(f.buffer.raw.closefd, True)
- file = self.open(f.fileno(), "r", closefd=False)
- self.assertEqual(file.buffer.raw.closefd, False)
- def test_garbage_collection(self):
- # FileIO objects are collected, and collecting them flushes
- # all data to disk.
- f = self.FileIO(support.TESTFN, "wb")
- f.write(b"abcxxx")
- f.f = f
- wr = weakref.ref(f)
- del f
- support.gc_collect()
- self.assertTrue(wr() is None, wr)
- with self.open(support.TESTFN, "rb") as f:
- self.assertEqual(f.read(), b"abcxxx")
- def test_unbounded_file(self):
- # Issue #1174606: reading from an unbounded stream such as /dev/zero.
- zero = "/dev/zero"
- if not os.path.exists(zero):
- self.skipTest("{0} does not exist".format(zero))
- if sys.maxsize > 0x7FFFFFFF:
- self.skipTest("test can only run in a 32-bit address space")
- if support.real_max_memuse < support._2G:
- self.skipTest("test requires at least 2GB of memory")
- with self.open(zero, "rb", buffering=0) as f:
- self.assertRaises(OverflowError, f.read)
- with self.open(zero, "rb") as f:
- self.assertRaises(OverflowError, f.read)
- with self.open(zero, "r") as f:
- self.assertRaises(OverflowError, f.read)
- def test_flush_error_on_close(self):
- f = self.open(support.TESTFN, "wb", buffering=0)
- def bad_flush():
- raise IOError()
- f.flush = bad_flush
- self.assertRaises(IOError, f.close) # exception not swallowed
- def test_multi_close(self):
- f = self.open(support.TESTFN, "wb", buffering=0)
- f.close()
- f.close()
- f.close()
- self.assertRaises(ValueError, f.flush)
- def test_RawIOBase_read(self):
- # Exercise the default RawIOBase.read() implementation (which calls
- # readinto() internally).
- rawio = self.MockRawIOWithoutRead((b"abc", b"d", None, b"efg", None))
- self.assertEqual(rawio.read(2), b"ab")
- self.assertEqual(rawio.read(2), b"c")
- self.assertEqual(rawio.read(2), b"d")
- self.assertEqual(rawio.read(2), None)
- self.assertEqual(rawio.read(2), b"ef")
- self.assertEqual(rawio.read(2), b"g")
- self.assertEqual(rawio.read(2), None)
- self.assertEqual(rawio.read(2), b"")
- class CIOTest(IOTest):
- pass
- class PyIOTest(IOTest):
- test_array_writes = unittest.skip(
- "len(array.array) returns number of elements rather than bytelength"
- )(IOTest.test_array_writes)
- class CommonBufferedTests:
- # Tests common to BufferedReader, BufferedWriter and BufferedRandom
- def test_detach(self):
- raw = self.MockRawIO()
- buf = self.tp(raw)
- self.assertIs(buf.detach(), raw)
- self.assertRaises(ValueError, buf.detach)
- def test_fileno(self):
- rawio = self.MockRawIO()
- bufio = self.tp(rawio)
- self.assertEqual(42, bufio.fileno())
- def test_no_fileno(self):
- # XXX will we always have fileno() function? If so, kill
- # this test. Else, write it.
- pass
- def test_invalid_args(self):
- rawio = self.MockRawIO()
- bufio = self.tp(rawio)
- # Invalid whence
- self.assertRaises(ValueError, bufio.seek, 0, -1)
- self.assertRaises(ValueError, bufio.seek, 0, 3)
- def test_override_destructor(self):
- tp = self.tp
- record = []
- class MyBufferedIO(tp):
- def __del__(self):
- record.append(1)
- try:
- f = super(MyBufferedIO, self).__del__
- except AttributeError:
- pass
- else:
- f()
- def close(self):
- record.append(2)
- super(MyBufferedIO, self).close()
- def flush(self):
- record.append(3)
- super(MyBufferedIO, self).flush()
- rawio = self.MockRawIO()
- bufio = MyBufferedIO(rawio)
- writable = bufio.writable()
- del bufio
- support.gc_collect()
- if writable:
- self.assertEqual(record, [1, 2, 3])
- else:
- self.assertEqual(record, [1, 2])
- def test_context_manager(self):
- # Test usability as a context manager
- rawio = self.MockRawIO()
- bufio = self.tp(rawio)
- def _with():
- with bufio:
- pass
- _with()
- # bufio should now be closed, and using it a second time should raise
- # a ValueError.
- self.assertRaises(ValueError, _with)
- def test_error_through_destructor(self):
- # Test that the exception state is not modified by a destructor,
- # even if close() fails.
- rawio = self.CloseFailureIO()
- def f():
- self.tp(rawio).xyzzy
- with support.captured_output("stderr") as s:
- self.assertRaises(AttributeError, f)
- s = s.getvalue().strip()
- if s:
- # The destructor *may* have printed an unraisable error, check it
- self.assertEqual(len(s.splitlines()), 1)
- self.assertTrue(s.startswith("Exception IOError: "), s)
- self.assertTrue(s.endswith(" ignored"), s)
- def test_repr(self):
- raw = self.MockRawIO()
- b = self.tp(raw)
- clsname = "%s.%s" % (self.tp.__module__, self.tp.__name__)
- self.assertEqual(repr(b), "<%s>" % clsname)
- raw.name = "dummy"
- self.assertEqual(repr(b), "<%s name=u'dummy'>" % clsname)
- raw.name = b"dummy"
- self.assertEqual(repr(b), "<%s name='dummy'>" % clsname)
- def test_flush_error_on_close(self):
- raw = self.MockRawIO()
- def bad_flush():
- raise IOError()
- raw.flush = bad_flush
- b = self.tp(raw)
- self.assertRaises(IOError, b.close) # exception not swallowed
- def test_multi_close(self):
- raw = self.MockRawIO()
- b = self.tp(raw)
- b.close()
- b.close()
- b.close()
- self.assertRaises(ValueError, b.flush)
- def test_readonly_attributes(self):
- raw = self.MockRawIO()
- buf = self.tp(raw)
- x = self.MockRawIO()
- with self.assertRaises((AttributeError, TypeError)):
- buf.raw = x
- class BufferedReaderTest(unittest.TestCase, CommonBufferedTests):
- read_mode = "rb"
- def test_constructor(self):
- rawio = self.MockRawIO([b"abc"])
- bufio = self.tp(rawio)
- bufio.__init__(rawio)
- bufio.__init__(rawio, buffer_size=1024)
- bufio.__init__(rawio, buffer_size=16)
- self.assertEqual(b"abc", bufio.read())
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0)
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16)
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1)
- rawio = self.MockRawIO([b"abc"])
- bufio.__init__(rawio)
- self.assertEqual(b"abc", bufio.read())
- def test_read(self):
- for arg in (None, 7):
- rawio = self.MockRawIO((b"abc", b"d", b"efg"))
- bufio = self.tp(rawio)
- self.assertEqual(b"abcdefg", bufio.read(arg))
- # Invalid args
- self.assertRaises(ValueError, bufio.read, -2)
- def test_read1(self):
- rawio = self.MockRawIO((b"abc", b"d", b"efg"))
- bufio = self.tp(rawio)
- self.assertEqual(b"a", bufio.read(1))
- self.assertEqual(b"b", bufio.read1(1))
- self.assertEqual(rawio._reads, 1)
- self.assertEqual(b"c", bufio.read1(100))
- self.assertEqual(rawio._reads, 1)
- self.assertEqual(b"d", bufio.read1(100))
- self.assertEqual(rawio._reads, 2)
- self.assertEqual(b"efg", bufio.read1(100))
- self.assertEqual(rawio._reads, 3)
- self.assertEqual(b"", bufio.read1(100))
- self.assertEqual(rawio._reads, 4)
- # Invalid args
- self.assertRaises(ValueError, bufio.read1, -1)
- def test_readinto(self):
- rawio = self.MockRawIO((b"abc", b"d", b"efg"))
- bufio = self.tp(rawio)
- b = bytearray(2)
- self.assertEqual(bufio.readinto(b), 2)
- self.assertEqual(b, b"ab")
- self.assertEqual(bufio.readinto(b), 2)
- self.assertEqual(b, b"cd")
- self.assertEqual(bufio.readinto(b), 2)
- self.assertEqual(b, b"ef")
- self.assertEqual(bufio.readinto(b), 1)
- self.assertEqual(b, b"gf")
- self.assertEqual(bufio.readinto(b), 0)
- self.assertEqual(b, b"gf")
- def test_readlines(self):
- def bufio():
- rawio = self.MockRawIO((b"abc\n", b"d\n", b"ef"))
- return self.tp(rawio)
- self.assertEqual(bufio().readlines(), [b"abc\n", b"d\n", b"ef"])
- self.assertEqual(bufio().readlines(5), [b"abc\n", b"d\n"])
- self.assertEqual(bufio().readlines(None), [b"abc\n", b"d\n", b"ef"])
- def test_buffering(self):
- data = b"abcdefghi"
- dlen = len(data)
- tests = [
- [ 100, [ 3, 1, 4, 8 ], [ dlen, 0 ] ],
- [ 100, [ 3, 3, 3], [ dlen ] ],
- [ 4, [ 1, 2, 4, 2 ], [ 4, 4, 1 ] ],
- ]
- for bufsize, buf_read_sizes, raw_read_sizes in tests:
- rawio = self.MockFileIO(data)
- bufio = self.tp(rawio, buffer_size=bufsize)
- pos = 0
- for nbytes in buf_read_sizes:
- self.assertEqual(bufio.read(nbytes), data[pos:pos+nbytes])
- pos += nbytes
- # this is mildly implementation-dependent
- self.assertEqual(rawio.read_history, raw_read_sizes)
- def test_read_non_blocking(self):
- # Inject some None's in there to simulate EWOULDBLOCK
- rawio = self.MockRawIO((b"abc", b"d", None, b"efg", None, None, None))
- bufio = self.tp(rawio)
- self.assertEqual(b"abcd", bufio.read(6))
- self.assertEqual(b"e", bufio.read(1))
- self.assertEqual(b"fg", bufio.read())
- self.assertEqual(b"", bufio.peek(1))
- self.assertIsNone(bufio.read())
- self.assertEqual(b"", bufio.read())
- rawio = self.MockRawIO((b"a", None, None))
- self.assertEqual(b"a", rawio.readall())
- self.assertIsNone(rawio.readall())
- def test_read_past_eof(self):
- rawio = self.MockRawIO((b"abc", b"d", b"efg"))
- bufio = self.tp(rawio)
- self.assertEqual(b"abcdefg", bufio.read(9000))
- def test_read_all(self):
- rawio = self.MockRawIO((b"abc", b"d", b"efg"))
- bufio = self.tp(rawio)
- self.assertEqual(b"abcdefg", bufio.read())
- @unittest.skipUnless(threading, 'Threading required for this test.')
- @support.requires_resource('cpu')
- def test_threads(self):
- try:
- # Write out many bytes with exactly the same number of 0's,
- # 1's... 255's. This will help us check that concurrent reading
- # doesn't duplicate or forget contents.
- N = 1000
- l = list(range(256)) * N
- random.shuffle(l)
- s = bytes(bytearray(l))
- with self.open(support.TESTFN, "wb") as f:
- f.write(s)
- with self.open(support.TESTFN, self.read_mode, buffering=0) as raw:
- bufio = self.tp(raw, 8)
- errors = []
- results = []
- def f():
- try:
- # Intra-buffer read then buffer-flushing read
- for n in cycle([1, 19]):
- s = bufio.read(n)
- if not s:
- break
- # list.append() is atomic
- results.append(s)
- except Exception as e:
- errors.append(e)
- raise
- threads = [threading.Thread(target=f) for x in range(20)]
- for t in threads:
- t.start()
- time.sleep(0.02) # yield
- for t in threads:
- t.join()
- self.assertFalse(errors,
- "the following exceptions were caught: %r" % errors)
- s = b''.join(results)
- for i in range(256):
- c = bytes(bytearray([i]))
- self.assertEqual(s.count(c), N)
- finally:
- support.unlink(support.TESTFN)
- def test_misbehaved_io(self):
- rawio = self.MisbehavedRawIO((b"abc", b"d", b"efg"))
- bufio = self.tp(rawio)
- self.assertRaises(IOError, bufio.seek, 0)
- self.assertRaises(IOError, bufio.tell)
- def test_no_extraneous_read(self):
- # Issue #9550; when the raw IO object has satisfied the read request,
- # we should not issue any additional reads, otherwise it may block
- # (e.g. socket).
- bufsize = 16
- for n in (2, bufsize - 1, bufsize, bufsize + 1, bufsize * 2):
- rawio = self.MockRawIO([b"x" * n])
- bufio = self.tp(rawio, bufsize)
- self.assertEqual(bufio.read(n), b"x" * n)
- # Simple case: one raw read is enough to satisfy the request.
- self.assertEqual(rawio._extraneous_reads, 0,
- "failed for {}: {} != 0".format(n, rawio._extraneous_reads))
- # A more complex case where two raw reads are needed to satisfy
- # the request.
- rawio = self.MockRawIO([b"x" * (n - 1), b"x"])
- bufio = self.tp(rawio, bufsize)
- self.assertEqual(bufio.read(n), b"x" * n)
- self.assertEqual(rawio._extraneous_reads, 0,
- "failed for {}: {} != 0".format(n, rawio._extraneous_reads))
- class CBufferedReaderTest(BufferedReaderTest):
- tp = io.BufferedReader
- def test_constructor(self):
- BufferedReaderTest.test_constructor(self)
- # The allocation can succeed on 32-bit builds, e.g. with more
- # than 2GB RAM and a 64-bit kernel.
- if sys.maxsize > 0x7FFFFFFF:
- rawio = self.MockRawIO()
- bufio = self.tp(rawio)
- self.assertRaises((OverflowError, MemoryError, ValueError),
- bufio.__init__, rawio, sys.maxsize)
- def test_initialization(self):
- rawio = self.MockRawIO([b"abc"])
- bufio = self.tp(rawio)
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0)
- self.assertRaises(ValueError, bufio.read)
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16)
- self.assertRaises(ValueError, bufio.read)
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1)
- self.assertRaises(ValueError, bufio.read)
- def test_misbehaved_io_read(self):
- rawio = self.MisbehavedRawIO((b"abc", b"d", b"efg"))
- bufio = self.tp(rawio)
- # _pyio.BufferedReader seems to implement reading different, so that
- # checking this is not so easy.
- self.assertRaises(IOError, bufio.read, 10)
- def test_garbage_collection(self):
- # C BufferedReader objects are collected.
- # The Python version has __del__, so it ends into gc.garbage instead
- rawio = self.FileIO(support.TESTFN, "w+b")
- f = self.tp(rawio)
- f.f = f
- wr = weakref.ref(f)
- del f
- support.gc_collect()
- self.assertTrue(wr() is None, wr)
- class PyBufferedReaderTest(BufferedReaderTest):
- tp = pyio.BufferedReader
- class BufferedWriterTest(unittest.TestCase, CommonBufferedTests):
- write_mode = "wb"
- def test_constructor(self):
- rawio = self.MockRawIO()
- bufio = self.tp(rawio)
- bufio.__init__(rawio)
- bufio.__init__(rawio, buffer_size=1024)
- bufio.__init__(rawio, buffer_size=16)
- self.assertEqual(3, bufio.write(b"abc"))
- bufio.flush()
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0)
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16)
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1)
- bufio.__init__(rawio)
- self.assertEqual(3, bufio.write(b"ghi"))
- bufio.flush()
- self.assertEqual(b"".join(rawio._write_stack), b"abcghi")
- def test_detach_flush(self):
- raw = self.MockRawIO()
- buf = self.tp(raw)
- buf.write(b"howdy!")
- self.assertFalse(raw._write_stack)
- buf.detach()
- self.assertEqual(raw._write_stack, [b"howdy!"])
- def test_write(self):
- # Write to the buffered IO but don't overflow the buffer.
- writer = self.MockRawIO()
- bufio = self.tp(writer, 8)
- bufio.write(b"abc")
- self.assertFalse(writer._write_stack)
- def test_write_overflow(self):
- writer = self.MockRawIO()
- bufio = self.tp(writer, 8)
- contents = b"abcdefghijklmnop"
- for n in range(0, len(contents), 3):
- bufio.write(contents[n:n+3])
- flushed = b"".join(writer._write_stack)
- # At least (total - 8) bytes were implicitly flushed, perhaps more
- # depending on the implementation.
- self.assertTrue(flushed.startswith(contents[:-8]), flushed)
- def check_writes(self, intermediate_func):
- # Lots of writes, test the flushed output is as expected.
- contents = bytes(range(256)) * 1000
- n = 0
- writer = self.MockRawIO()
- bufio = self.tp(writer, 13)
- # Generator of write sizes: repeat each N 15 times then proceed to N+1
- def gen_sizes():
- for size in count(1):
- for i in range(15):
- yield size
- sizes = gen_sizes()
- while n < len(contents):
- size = min(next(sizes), len(contents) - n)
- self.assertEqual(bufio.write(contents[n:n+size]), size)
- intermediate_func(bufio)
- n += size
- bufio.flush()
- self.assertEqual(contents,
- b"".join(writer._write_stack))
- def test_writes(self):
- self.check_writes(lambda bufio: None)
- def test_writes_and_flushes(self):
- self.check_writes(lambda bufio: bufio.flush())
- def test_writes_and_seeks(self):
- def _seekabs(bufio):
- pos = bufio.tell()
- bufio.seek(pos + 1, 0)
- bufio.seek(pos - 1, 0)
- bufio.seek(pos, 0)
- self.check_writes(_seekabs)
- def _seekrel(bufio):
- pos = bufio.seek(0, 1)
- bufio.seek(+1, 1)
- bufio.seek(-1, 1)
- bufio.seek(pos, 0)
- self.check_writes(_seekrel)
- def test_writes_and_truncates(self):
- self.check_writes(lambda bufio: bufio.truncate(bufio.tell()))
- def test_write_non_blocking(self):
- raw = self.MockNonBlockWriterIO()
- bufio = self.tp(raw, 8)
- self.assertEqual(bufio.write(b"abcd"), 4)
- self.assertEqual(bufio.write(b"efghi"), 5)
- # 1 byte will be written, the rest will be buffered
- raw.block_on(b"k")
- self.assertEqual(bufio.write(b"jklmn"), 5)
- # 8 bytes will be written, 8 will be buffered and the rest will be lost
- raw.block_on(b"0")
- try:
- bufio.write(b"opqrwxyz0123456789")
- except self.BlockingIOError as e:
- written = e.characters_written
- else:
- self.fail("BlockingIOError should have been raised")
- self.assertEqual(written, 16)
- self.assertEqual(raw.pop_written(),
- b"abcdefghijklmnopqrwxyz")
- self.assertEqual(bufio.write(b"ABCDEFGHI"), 9)
- s = raw.pop_written()
- # Previously buffered bytes were flushed
- self.assertTrue(s.startswith(b"01234567A"), s)
- def test_write_and_rewind(self):
- raw = io.BytesIO()
- bufio = self.tp(raw, 4)
- self.assertEqual(bufio.write(b"abcdef"), 6)
- self.assertEqual(bufio.tell(), 6)
- bufio.seek(0, 0)
- self.assertEqual(bufio.write(b"XY"), 2)
- bufio.seek(6, 0)
- self.assertEqual(raw.getvalue(), b"XYcdef")
- self.assertEqual(bufio.write(b"123456"), 6)
- bufio.flush()
- self.assertEqual(raw.getvalue(), b"XYcdef123456")
- def test_flush(self):
- writer = self.MockRawIO()
- bufio = self.tp(writer, 8)
- bufio.write(b"abc")
- bufio.flush()
- self.assertEqual(b"abc", writer._write_stack[0])
- def test_destructor(self):
- writer = self.MockRawIO()
- bufio = self.tp(writer, 8)
- bufio.write(b"abc")
- del bufio
- support.gc_collect()
- self.assertEqual(b"abc", writer._write_stack[0])
- def test_truncate(self):
- # Truncate implicitly flushes the buffer.
- with self.open(support.TESTFN, self.write_mode, buffering=0) as raw:
- bufio = self.tp(raw, 8)
- bufio.write(b"abcdef")
- self.assertEqual(bufio.truncate(3), 3)
- self.assertEqual(bufio.tell(), 6)
- with self.open(support.TESTFN, "rb", buffering=0) as f:
- self.assertEqual(f.read(), b"abc")
- @unittest.skipUnless(threading, 'Threading required for this test.')
- @support.requires_resource('cpu')
- def test_threads(self):
- try:
- # Write out many bytes from many threads and test they were
- # all flushed.
- N = 1000
- contents = bytes(range(256)) * N
- sizes = cycle([1, 19])
- n = 0
- queue = deque()
- while n < len(contents):
- size = next(sizes)
- queue.append(contents[n:n+size])
- n += size
- del contents
- # We use a real file object because it allows us to
- # exercise situations where the GIL is released before
- # writing the buffer to the raw streams. This is in addition
- # to concurrency issues due to switching threads in the middle
- # of Python code.
- with self.open(support.TESTFN, self.write_mode, buffering=0) as raw:
- bufio = self.tp(raw, 8)
- errors = []
- def f():
- try:
- while True:
- try:
- s = queue.popleft()
- except IndexError:
- return
- bufio.write(s)
- except Exception as e:
- errors.append(e)
- raise
- threads = [threading.Thread(target=f) for x in range(20)]
- for t in threads:
- t.start()
- time.sleep(0.02) # yield
- for t in threads:
- t.join()
- self.assertFalse(errors,
- "the following exceptions were caught: %r" % errors)
- bufio.close()
- with self.open(support.TESTFN, "rb") as f:
- s = f.read()
- for i in range(256):
- self.assertEqual(s.count(bytes([i])), N)
- finally:
- support.unlink(support.TESTFN)
- def test_misbehaved_io(self):
- rawio = self.MisbehavedRawIO()
- bufio = self.tp(rawio, 5)
- self.assertRaises(IOError, bufio.seek, 0)
- self.assertRaises(IOError, bufio.tell)
- self.assertRaises(IOError, bufio.write, b"abcdef")
- def test_max_buffer_size_deprecation(self):
- with support.check_warnings(("max_buffer_size is deprecated",
- DeprecationWarning)):
- self.tp(self.MockRawIO(), 8, 12)
- class CBufferedWriterTest(BufferedWriterTest):
- tp = io.BufferedWriter
- def test_constructor(self):
- BufferedWriterTest.test_constructor(self)
- # The allocation can succeed on 32-bit builds, e.g. with more
- # than 2GB RAM and a 64-bit kernel.
- if sys.maxsize > 0x7FFFFFFF:
- rawio = self.MockRawIO()
- bufio = self.tp(rawio)
- self.assertRaises((OverflowError, MemoryError, ValueError),
- bufio.__init__, rawio, sys.maxsize)
- def test_initialization(self):
- rawio = self.MockRawIO()
- bufio = self.tp(rawio)
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0)
- self.assertRaises(ValueError, bufio.write, b"def")
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16)
- self.assertRaises(ValueError, bufio.write, b"def")
- self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1)
- self.assertRaises(ValueError, bufio.write, b"def")
- def test_garbage_collection(self):
- # C BufferedWriter objects are collected, and collecting them flushes
- # all data to disk.
- # The Python version has __del__, so it ends into gc.garbage instead
- rawio = self.FileIO(support.TESTFN, "w+b")
- f = self.tp(rawio)
- f.write(b"123xxx")
- f.x = f
- wr = weakref.ref(f)
- del f
- support.gc_collect()
- self.assertTrue(wr() is None, wr)
- with self.open(support.TESTFN, "rb") as f:
- self.assertEqual(f.read(), b"123xxx")
- class PyBufferedWriterTest(BufferedWriterTest):
- tp = pyio.BufferedWriter
- class BufferedRWPairTest(unittest.TestCase):
- def test_constructor(self):
- pair = self.tp(self.MockRawIO(), self.MockRawIO())
- self.assertFalse(pair.closed)
- def test_detach(self):
- pair = self.tp(self.MockRawIO(), self.MockRawIO())
- self.assertRaises(self.UnsupportedOperation, pair.detach)
- def test_constructor_max_buffer_size_deprecation(self):
- with support.check_warnings(("max_buffer_size is deprecated",
- DeprecationWarning)):
- self.tp(self.MockRawIO(), self.MockRawIO(), 8, 12)
- def test_constructor_with_not_readable(self):
- class NotReadable(MockRawIO):
- def readable(self):
- return False
- self.assertRaises(IOError, self.tp, NotReadable(), self.MockRawIO())
- def test_constructor_with_not_writeable(self):
- class NotWriteable(MockRawIO):
- def writable(self):
- return False
- self.assertRaises(IOError, self.tp, self.MockRawIO(), NotWriteable())
- def test_read(self):
- pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO())
- self.assertEqual(pair.read(3), b"abc")
- self.assertEqual(pair.read(1), b"d")
- self.assertEqual(pair.read(), b"ef")
- pair = self.tp(self.BytesIO(b"abc"), self.MockRawIO())
- self.assertEqual(pair.read(None), b"abc")
- def test_readlines(self):
- pair = lambda: self.tp(self.BytesIO(b"abc\ndef\nh"), self.MockRawIO())
- self.assertEqual(pair().readlines(), [b"abc\n", b"def\n", b"h"])
- self.assertEqual(pair().readlines(), [b"abc\n", b"def\n", b"h"])
- self.assertEqual(pair().readlines(5), [b"abc\n", b"def\n"])
- def test_read1(self):
- # .read1() is delegated to the underlying reader object, so this test
- # can be shallow.
- pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO())
- self.assertEqual(pair.read1(3), b"abc")
- def test_readinto(self):
- pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO())
- data = bytearray(5)
- self.assertEqual(pair.readinto(data), 5)
- self.assertEqual(data, b"abcde")
- def test_write(self):
- w = self.MockRawIO()
- pair = self.tp(self.MockRawIO(), w)
- pair.write(b"abc")
- pair.flush()
- pair.write(b"def")
- pair.flush()
- self.assertEqual(w._write_stack, [b"abc", b"def"])
- def test_peek(self):
- pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO())
- self.assertTrue(pair.peek(3).startswith(b"abc"))
- self.assertEqual(pair.read(3), b"abc")
- def test_readable(self):
- pair = self.tp(self.MockRawIO(), self.MockRawIO())
- self.assertTrue(pair.readable())
- def test_writeable(self):
- pair = self.tp(self.MockRawIO(), self.MockRawIO())
- self.assertTrue(pair.writable())
- def test_seekable(self):
- # BufferedRWPairs are never seekable, even if their readers and writers
- # are.
- pair = self.tp(self.MockRawIO(), self.MockRawIO())
- self.assertFalse(pair.seekable())
- # .flush() is delegated to the underlying writer object and has been
- # tested in the test_write method.
- def test_close_and_closed(self):
- pair = self.tp(self.MockRawIO(), self.MockRawIO())
- self.assertFalse(pair.closed)
- pair.close()
- self.assertTrue(pair.closed)
- def test_isatty(self):
- class SelectableIsAtty(MockRawIO):
- def __init__(self, isatty):
- MockRawIO.__init__(self)
- self._isatty = isatty
- def isatty(self):
- return self._isatty
- pair = self.tp(SelectableIsAtty(False), SelectableIsAtty(False))
- self.assertFalse(pair.isatty())
- pair = self.tp(SelectableIsAtty(True), SelectableIsAtty(False))
- self.assertTrue(pair.isatty())
- pair = self.tp(SelectableIsAtty(False), SelectableIsAtty(True))
- self.assertTrue(pair.isatty())
- pair = self.tp(SelectableIsAtty(True), SelectableIsAtty(True))
- self.assertTrue(pair.isatty())
- class CBufferedRWPairTest(BufferedRWPairTest):
- tp = io.BufferedRWPair
- class PyBufferedRWPairTest(BufferedRWPairTest):
- tp = pyio.BufferedRWPair
- class BufferedRandomTest(BufferedReaderTest, BufferedWriterTest):
- read_mode = "rb+"
- write_mode = "wb+"
- def test_constructor(self):
- BufferedReaderTest.test_constructor(self)
- BufferedWriterTest.test_constructor(self)
- def test_read_and_write(self):
- raw = self.MockRawIO((b"asdf", b"ghjk"))
- rw = self.tp(raw, 8)
- self.assertEqual(b"as", rw.read(2))
- rw.write(b"ddd")
- rw.write(b"eee")
- self.assertFalse(raw._write_stack) # Buffer writes
- self.assertEqual(b"ghjk", rw.read())
- self.assertEqual(b"dddeee", raw._write_stack[0])
- def test_seek_and_tell(self):
- raw = self.BytesIO(b"asdfghjkl")
- rw = self.tp(raw)
- self.assertEqual(b"as", rw.read(2))
- self.assertEqual(2, rw.tell())
- rw.seek(0, 0)
- self.assertEqual(b"asdf", rw.read(4))
- rw.write(b"asdf")
- rw.seek(0, 0)
- self.assertEqual(b"asdfasdfl", rw.read())
- self.assertEqual(9, rw.tell())
- rw.seek(-4, 2)
- self.assertEqual(5, rw.tell())
- rw.seek(2, 1)
- self.assertEqual(7, rw.tell())
- self.assertEqual(b"fl", rw.read(11))
- self.assertRaises(TypeError, rw.seek, 0.0)
- def check_flush_and_read(self, read_func):
- raw = self.BytesIO(b"abcdefghi")
- bufio = self.tp(raw)
- self.assertEqual(b"ab", read_func(bufio, 2))
- bufio.write(b"12")
- self.assertEqual(b"ef", read_func(bufio, 2))
- self.assertEqual(6, bufio.tell())
- bufio.flush()
- self.assertEqual(6, bufio.tell())
- self.assertEqual(b"ghi", read_func(bufio))
- raw.seek(0, 0)
- raw.write(b"XYZ")
- # flush() resets the read buffer
- bufio.flush()
- bufio.seek(0, 0)
- self.assertEqual(b"XYZ", read_func(bufio, 3))
- def test_flush_and_read(self):
- self.check_flush_and_read(lambda bufio, *args: bufio.read(*args))
- def test_flush_and_readinto(self):
- def _readinto(bufio, n=-1):
- b = bytearray(n if n >= 0 else 9999)
- n = bufio.readinto(b)
- return bytes(b[:n])
- self.check_flush_and_read(_readinto)
- def test_flush_and_peek(self):
- def _peek(bufio, n=-1):
- # This relies on the fact that the buffer can contain the whole
- # raw stream, otherwise peek() can return less.
- b = bufio.peek(n)
- if n != -1:
- b = b[:n]
- bufio.seek(len(b), 1)
- return b
- self.check_flush_and_read(_peek)
- def test_flush_and_write(self):
- raw = self.BytesIO(b"abcdefghi")
- bufio = self.tp(raw)
- bufio.write(b"123")
- bufio.flush()
- bufio.write(b"45")
- bufio.flush()
- bufio.seek(0, 0)
- self.assertEqual(b"12345fghi", raw.getvalue())
- self.assertEqual(b"12345fghi", bufio.read())
- def test_threads(self):
- BufferedReaderTest.test_threads(self)
- BufferedWriterTest.test_threads(self)
- def test_writes_and_peek(self):
- def _peek(bufio):
- bufio.peek(1)
- self.check_writes(_peek)
- def _peek(bufio):
- pos = bufio.tell()
- bufio.seek(-1, 1)
- bufio.peek(1)
- bufio.seek(pos, 0)
- self.check_writes(_peek)
- def test_writes_and_reads(self):
- def _read(bufio):
- bufio.seek(-1, 1)
- bufio.read(1)
- self…