Home | History | Annotate | Download | only in test
      1 """Unit tests for memory-based file-like objects.
      2 StringIO -- for unicode strings
      3 BytesIO -- for bytes
      4 """
      5 
      6 import unittest
      7 from test import support
      8 
      9 import io
     10 import _pyio as pyio
     11 import pickle
     12 import sys
     13 
     14 class MemorySeekTestMixin:
     15 
     16     def testInit(self):
     17         buf = self.buftype("1234567890")
     18         bytesIo = self.ioclass(buf)
     19 
     20     def testRead(self):
     21         buf = self.buftype("1234567890")
     22         bytesIo = self.ioclass(buf)
     23 
     24         self.assertEqual(buf[:1], bytesIo.read(1))
     25         self.assertEqual(buf[1:5], bytesIo.read(4))
     26         self.assertEqual(buf[5:], bytesIo.read(900))
     27         self.assertEqual(self.EOF, bytesIo.read())
     28 
     29     def testReadNoArgs(self):
     30         buf = self.buftype("1234567890")
     31         bytesIo = self.ioclass(buf)
     32 
     33         self.assertEqual(buf, bytesIo.read())
     34         self.assertEqual(self.EOF, bytesIo.read())
     35 
     36     def testSeek(self):
     37         buf = self.buftype("1234567890")
     38         bytesIo = self.ioclass(buf)
     39 
     40         bytesIo.read(5)
     41         bytesIo.seek(0)
     42         self.assertEqual(buf, bytesIo.read())
     43 
     44         bytesIo.seek(3)
     45         self.assertEqual(buf[3:], bytesIo.read())
     46         self.assertRaises(TypeError, bytesIo.seek, 0.0)
     47 
     48     def testTell(self):
     49         buf = self.buftype("1234567890")
     50         bytesIo = self.ioclass(buf)
     51 
     52         self.assertEqual(0, bytesIo.tell())
     53         bytesIo.seek(5)
     54         self.assertEqual(5, bytesIo.tell())
     55         bytesIo.seek(10000)
     56         self.assertEqual(10000, bytesIo.tell())
     57 
     58 
     59 class MemoryTestMixin:
     60 
     61     def test_detach(self):
     62         buf = self.ioclass()
     63         self.assertRaises(self.UnsupportedOperation, buf.detach)
     64 
     65     def write_ops(self, f, t):
     66         self.assertEqual(f.write(t("blah.")), 5)
     67         self.assertEqual(f.seek(0), 0)
     68         self.assertEqual(f.write(t("Hello.")), 6)
     69         self.assertEqual(f.tell(), 6)
     70         self.assertEqual(f.seek(5), 5)
     71         self.assertEqual(f.tell(), 5)
     72         self.assertEqual(f.write(t(" world\n\n\n")), 9)
     73         self.assertEqual(f.seek(0), 0)
     74         self.assertEqual(f.write(t("h")), 1)
     75         self.assertEqual(f.truncate(12), 12)
     76         self.assertEqual(f.tell(), 1)
     77 
     78     def test_write(self):
     79         buf = self.buftype("hello world\n")
     80         memio = self.ioclass(buf)
     81 
     82         self.write_ops(memio, self.buftype)
     83         self.assertEqual(memio.getvalue(), buf)
     84         memio = self.ioclass()
     85         self.write_ops(memio, self.buftype)
     86         self.assertEqual(memio.getvalue(), buf)
     87         self.assertRaises(TypeError, memio.write, None)
     88         memio.close()
     89         self.assertRaises(ValueError, memio.write, self.buftype(""))
     90 
     91     def test_writelines(self):
     92         buf = self.buftype("1234567890")
     93         memio = self.ioclass()
     94 
     95         self.assertEqual(memio.writelines([buf] * 100), None)
     96         self.assertEqual(memio.getvalue(), buf * 100)
     97         memio.writelines([])
     98         self.assertEqual(memio.getvalue(), buf * 100)
     99         memio = self.ioclass()
    100         self.assertRaises(TypeError, memio.writelines, [buf] + [1])
    101         self.assertEqual(memio.getvalue(), buf)
    102         self.assertRaises(TypeError, memio.writelines, None)
    103         memio.close()
    104         self.assertRaises(ValueError, memio.writelines, [])
    105 
    106     def test_writelines_error(self):
    107         memio = self.ioclass()
    108         def error_gen():
    109             yield self.buftype('spam')
    110             raise KeyboardInterrupt
    111 
    112         self.assertRaises(KeyboardInterrupt, memio.writelines, error_gen())
    113 
    114     def test_truncate(self):
    115         buf = self.buftype("1234567890")
    116         memio = self.ioclass(buf)
    117 
    118         self.assertRaises(ValueError, memio.truncate, -1)
    119         memio.seek(6)
    120         self.assertEqual(memio.truncate(), 6)
    121         self.assertEqual(memio.getvalue(), buf[:6])
    122         self.assertEqual(memio.truncate(4), 4)
    123         self.assertEqual(memio.getvalue(), buf[:4])
    124         self.assertEqual(memio.tell(), 6)
    125         memio.seek(0, 2)
    126         memio.write(buf)
    127         self.assertEqual(memio.getvalue(), buf[:4] + buf)
    128         pos = memio.tell()
    129         self.assertEqual(memio.truncate(None), pos)
    130         self.assertEqual(memio.tell(), pos)
    131         self.assertRaises(TypeError, memio.truncate, '0')
    132         memio.close()
    133         self.assertRaises(ValueError, memio.truncate, 0)
    134 
    135     def test_init(self):
    136         buf = self.buftype("1234567890")
    137         memio = self.ioclass(buf)
    138         self.assertEqual(memio.getvalue(), buf)
    139         memio = self.ioclass(None)
    140         self.assertEqual(memio.getvalue(), self.EOF)
    141         memio.__init__(buf * 2)
    142         self.assertEqual(memio.getvalue(), buf * 2)
    143         memio.__init__(buf)
    144         self.assertEqual(memio.getvalue(), buf)
    145         self.assertRaises(TypeError, memio.__init__, [])
    146 
    147     def test_read(self):
    148         buf = self.buftype("1234567890")
    149         memio = self.ioclass(buf)
    150 
    151         self.assertEqual(memio.read(0), self.EOF)
    152         self.assertEqual(memio.read(1), buf[:1])
    153         self.assertEqual(memio.read(4), buf[1:5])
    154         self.assertEqual(memio.read(900), buf[5:])
    155         self.assertEqual(memio.read(), self.EOF)
    156         memio.seek(0)
    157         self.assertEqual(memio.read(), buf)
    158         self.assertEqual(memio.read(), self.EOF)
    159         self.assertEqual(memio.tell(), 10)
    160         memio.seek(0)
    161         self.assertEqual(memio.read(-1), buf)
    162         memio.seek(0)
    163         self.assertEqual(type(memio.read()), type(buf))
    164         memio.seek(100)
    165         self.assertEqual(type(memio.read()), type(buf))
    166         memio.seek(0)
    167         self.assertEqual(memio.read(None), buf)
    168         self.assertRaises(TypeError, memio.read, '')
    169         memio.seek(len(buf) + 1)
    170         self.assertEqual(memio.read(1), self.EOF)
    171         memio.seek(len(buf) + 1)
    172         self.assertEqual(memio.read(), self.EOF)
    173         memio.close()
    174         self.assertRaises(ValueError, memio.read)
    175 
    176     def test_readline(self):
    177         buf = self.buftype("1234567890\n")
    178         memio = self.ioclass(buf * 2)
    179 
    180         self.assertEqual(memio.readline(0), self.EOF)
    181         self.assertEqual(memio.readline(), buf)
    182         self.assertEqual(memio.readline(), buf)
    183         self.assertEqual(memio.readline(), self.EOF)
    184         memio.seek(0)
    185         self.assertEqual(memio.readline(5), buf[:5])
    186         self.assertEqual(memio.readline(5), buf[5:10])
    187         self.assertEqual(memio.readline(5), buf[10:15])
    188         memio.seek(0)
    189         self.assertEqual(memio.readline(-1), buf)
    190         memio.seek(0)
    191         self.assertEqual(memio.readline(0), self.EOF)
    192         # Issue #24989: Buffer overread
    193         memio.seek(len(buf) * 2 + 1)
    194         self.assertEqual(memio.readline(), self.EOF)
    195 
    196         buf = self.buftype("1234567890\n")
    197         memio = self.ioclass((buf * 3)[:-1])
    198         self.assertEqual(memio.readline(), buf)
    199         self.assertEqual(memio.readline(), buf)
    200         self.assertEqual(memio.readline(), buf[:-1])
    201         self.assertEqual(memio.readline(), self.EOF)
    202         memio.seek(0)
    203         self.assertEqual(type(memio.readline()), type(buf))
    204         self.assertEqual(memio.readline(), buf)
    205         self.assertRaises(TypeError, memio.readline, '')
    206         memio.close()
    207         self.assertRaises(ValueError,  memio.readline)
    208 
    209     def test_readlines(self):
    210         buf = self.buftype("1234567890\n")
    211         memio = self.ioclass(buf * 10)
    212 
    213         self.assertEqual(memio.readlines(), [buf] * 10)
    214         memio.seek(5)
    215         self.assertEqual(memio.readlines(), [buf[5:]] + [buf] * 9)
    216         memio.seek(0)
    217         self.assertEqual(memio.readlines(15), [buf] * 2)
    218         memio.seek(0)
    219         self.assertEqual(memio.readlines(-1), [buf] * 10)
    220         memio.seek(0)
    221         self.assertEqual(memio.readlines(0), [buf] * 10)
    222         memio.seek(0)
    223         self.assertEqual(type(memio.readlines()[0]), type(buf))
    224         memio.seek(0)
    225         self.assertEqual(memio.readlines(None), [buf] * 10)
    226         self.assertRaises(TypeError, memio.readlines, '')
    227         # Issue #24989: Buffer overread
    228         memio.seek(len(buf) * 10 + 1)
    229         self.assertEqual(memio.readlines(), [])
    230         memio.close()
    231         self.assertRaises(ValueError, memio.readlines)
    232 
    233     def test_iterator(self):
    234         buf = self.buftype("1234567890\n")
    235         memio = self.ioclass(buf * 10)
    236 
    237         self.assertEqual(iter(memio), memio)
    238         self.assertTrue(hasattr(memio, '__iter__'))
    239         self.assertTrue(hasattr(memio, '__next__'))
    240         i = 0
    241         for line in memio:
    242             self.assertEqual(line, buf)
    243             i += 1
    244         self.assertEqual(i, 10)
    245         memio.seek(0)
    246         i = 0
    247         for line in memio:
    248             self.assertEqual(line, buf)
    249             i += 1
    250         self.assertEqual(i, 10)
    251         # Issue #24989: Buffer overread
    252         memio.seek(len(buf) * 10 + 1)
    253         self.assertEqual(list(memio), [])
    254         memio = self.ioclass(buf * 2)
    255         memio.close()
    256         self.assertRaises(ValueError, memio.__next__)
    257 
    258     def test_getvalue(self):
    259         buf = self.buftype("1234567890")
    260         memio = self.ioclass(buf)
    261 
    262         self.assertEqual(memio.getvalue(), buf)
    263         memio.read()
    264         self.assertEqual(memio.getvalue(), buf)
    265         self.assertEqual(type(memio.getvalue()), type(buf))
    266         memio = self.ioclass(buf * 1000)
    267         self.assertEqual(memio.getvalue()[-3:], self.buftype("890"))
    268         memio = self.ioclass(buf)
    269         memio.close()
    270         self.assertRaises(ValueError, memio.getvalue)
    271 
    272     def test_seek(self):
    273         buf = self.buftype("1234567890")
    274         memio = self.ioclass(buf)
    275 
    276         memio.read(5)
    277         self.assertRaises(ValueError, memio.seek, -1)
    278         self.assertRaises(ValueError, memio.seek, 1, -1)
    279         self.assertRaises(ValueError, memio.seek, 1, 3)
    280         self.assertEqual(memio.seek(0), 0)
    281         self.assertEqual(memio.seek(0, 0), 0)
    282         self.assertEqual(memio.read(), buf)
    283         self.assertEqual(memio.seek(3), 3)
    284         self.assertEqual(memio.seek(0, 1), 3)
    285         self.assertEqual(memio.read(), buf[3:])
    286         self.assertEqual(memio.seek(len(buf)), len(buf))
    287         self.assertEqual(memio.read(), self.EOF)
    288         memio.seek(len(buf) + 1)
    289         self.assertEqual(memio.read(), self.EOF)
    290         self.assertEqual(memio.seek(0, 2), len(buf))
    291         self.assertEqual(memio.read(), self.EOF)
    292         memio.close()
    293         self.assertRaises(ValueError, memio.seek, 0)
    294 
    295     def test_overseek(self):
    296         buf = self.buftype("1234567890")
    297         memio = self.ioclass(buf)
    298 
    299         self.assertEqual(memio.seek(len(buf) + 1), 11)
    300         self.assertEqual(memio.read(), self.EOF)
    301         self.assertEqual(memio.tell(), 11)
    302         self.assertEqual(memio.getvalue(), buf)
    303         memio.write(self.EOF)
    304         self.assertEqual(memio.getvalue(), buf)
    305         memio.write(buf)
    306         self.assertEqual(memio.getvalue(), buf + self.buftype('\0') + buf)
    307 
    308     def test_tell(self):
    309         buf = self.buftype("1234567890")
    310         memio = self.ioclass(buf)
    311 
    312         self.assertEqual(memio.tell(), 0)
    313         memio.seek(5)
    314         self.assertEqual(memio.tell(), 5)
    315         memio.seek(10000)
    316         self.assertEqual(memio.tell(), 10000)
    317         memio.close()
    318         self.assertRaises(ValueError, memio.tell)
    319 
    320     def test_flush(self):
    321         buf = self.buftype("1234567890")
    322         memio = self.ioclass(buf)
    323 
    324         self.assertEqual(memio.flush(), None)
    325 
    326     def test_flags(self):
    327         memio = self.ioclass()
    328 
    329         self.assertEqual(memio.writable(), True)
    330         self.assertEqual(memio.readable(), True)
    331         self.assertEqual(memio.seekable(), True)
    332         self.assertEqual(memio.isatty(), False)
    333         self.assertEqual(memio.closed, False)
    334         memio.close()
    335         self.assertRaises(ValueError, memio.writable)
    336         self.assertRaises(ValueError, memio.readable)
    337         self.assertRaises(ValueError, memio.seekable)
    338         self.assertRaises(ValueError, memio.isatty)
    339         self.assertEqual(memio.closed, True)
    340 
    341     def test_subclassing(self):
    342         buf = self.buftype("1234567890")
    343         def test1():
    344             class MemIO(self.ioclass):
    345                 pass
    346             m = MemIO(buf)
    347             return m.getvalue()
    348         def test2():
    349             class MemIO(self.ioclass):
    350                 def __init__(me, a, b):
    351                     self.ioclass.__init__(me, a)
    352             m = MemIO(buf, None)
    353             return m.getvalue()
    354         self.assertEqual(test1(), buf)
    355         self.assertEqual(test2(), buf)
    356 
    357     def test_instance_dict_leak(self):
    358         # Test case for issue #6242.
    359         # This will be caught by regrtest.py -R if this leak.
    360         for _ in range(100):
    361             memio = self.ioclass()
    362             memio.foo = 1
    363 
    364     def test_pickling(self):
    365         buf = self.buftype("1234567890")
    366         memio = self.ioclass(buf)
    367         memio.foo = 42
    368         memio.seek(2)
    369 
    370         class PickleTestMemIO(self.ioclass):
    371             def __init__(me, initvalue, foo):
    372                 self.ioclass.__init__(me, initvalue)
    373                 me.foo = foo
    374             # __getnewargs__ is undefined on purpose. This checks that PEP 307
    375             # is used to provide pickling support.
    376 
    377         # Pickle expects the class to be on the module level. Here we use a
    378         # little hack to allow the PickleTestMemIO class to derive from
    379         # self.ioclass without having to define all combinations explicitly on
    380         # the module-level.
    381         import __main__
    382         PickleTestMemIO.__module__ = '__main__'
    383         PickleTestMemIO.__qualname__ = PickleTestMemIO.__name__
    384         __main__.PickleTestMemIO = PickleTestMemIO
    385         submemio = PickleTestMemIO(buf, 80)
    386         submemio.seek(2)
    387 
    388         # We only support pickle protocol 2 and onward since we use extended
    389         # __reduce__ API of PEP 307 to provide pickling support.
    390         for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
    391             for obj in (memio, submemio):
    392                 obj2 = pickle.loads(pickle.dumps(obj, protocol=proto))
    393                 self.assertEqual(obj.getvalue(), obj2.getvalue())
    394                 self.assertEqual(obj.__class__, obj2.__class__)
    395                 self.assertEqual(obj.foo, obj2.foo)
    396                 self.assertEqual(obj.tell(), obj2.tell())
    397                 obj2.close()
    398                 self.assertRaises(ValueError, pickle.dumps, obj2, proto)
    399         del __main__.PickleTestMemIO
    400 
    401 
    402 class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
    403     # Test _pyio.BytesIO; class also inherited for testing C implementation
    404 
    405     UnsupportedOperation = pyio.UnsupportedOperation
    406 
    407     @staticmethod
    408     def buftype(s):
    409         return s.encode("ascii")
    410     ioclass = pyio.BytesIO
    411     EOF = b""
    412 
    413     def test_getbuffer(self):
    414         memio = self.ioclass(b"1234567890")
    415         buf = memio.getbuffer()
    416         self.assertEqual(bytes(buf), b"1234567890")
    417         memio.seek(5)
    418         buf = memio.getbuffer()
    419         self.assertEqual(bytes(buf), b"1234567890")
    420         # Trying to change the size of the BytesIO while a buffer is exported
    421         # raises a BufferError.
    422         self.assertRaises(BufferError, memio.write, b'x' * 100)
    423         self.assertRaises(BufferError, memio.truncate)
    424         self.assertRaises(BufferError, memio.close)
    425         self.assertFalse(memio.closed)
    426         # Mutating the buffer updates the BytesIO
    427         buf[3:6] = b"abc"
    428         self.assertEqual(bytes(buf), b"123abc7890")
    429         self.assertEqual(memio.getvalue(), b"123abc7890")
    430         # After the buffer gets released, we can resize and close the BytesIO
    431         # again
    432         del buf
    433         support.gc_collect()
    434         memio.truncate()
    435         memio.close()
    436         self.assertRaises(ValueError, memio.getbuffer)
    437 
    438     def test_read1(self):
    439         buf = self.buftype("1234567890")
    440         memio = self.ioclass(buf)
    441 
    442         self.assertRaises(TypeError, memio.read1)
    443         self.assertEqual(memio.read(), buf)
    444 
    445     def test_readinto(self):
    446         buf = self.buftype("1234567890")
    447         memio = self.ioclass(buf)
    448 
    449         b = bytearray(b"hello")
    450         self.assertEqual(memio.readinto(b), 5)
    451         self.assertEqual(b, b"12345")
    452         self.assertEqual(memio.readinto(b), 5)
    453         self.assertEqual(b, b"67890")
    454         self.assertEqual(memio.readinto(b), 0)
    455         self.assertEqual(b, b"67890")
    456         b = bytearray(b"hello world")
    457         memio.seek(0)
    458         self.assertEqual(memio.readinto(b), 10)
    459         self.assertEqual(b, b"1234567890d")
    460         b = bytearray(b"")
    461         memio.seek(0)
    462         self.assertEqual(memio.readinto(b), 0)
    463         self.assertEqual(b, b"")
    464         self.assertRaises(TypeError, memio.readinto, '')
    465         import array
    466         a = array.array('b', b"hello world")
    467         memio = self.ioclass(buf)
    468         memio.readinto(a)
    469         self.assertEqual(a.tobytes(), b"1234567890d")
    470         memio.close()
    471         self.assertRaises(ValueError, memio.readinto, b)
    472         memio = self.ioclass(b"123")
    473         b = bytearray()
    474         memio.seek(42)
    475         memio.readinto(b)
    476         self.assertEqual(b, b"")
    477 
    478     def test_relative_seek(self):
    479         buf = self.buftype("1234567890")
    480         memio = self.ioclass(buf)
    481 
    482         self.assertEqual(memio.seek(-1, 1), 0)
    483         self.assertEqual(memio.seek(3, 1), 3)
    484         self.assertEqual(memio.seek(-4, 1), 0)
    485         self.assertEqual(memio.seek(-1, 2), 9)
    486         self.assertEqual(memio.seek(1, 1), 10)
    487         self.assertEqual(memio.seek(1, 2), 11)
    488         memio.seek(-3, 2)
    489         self.assertEqual(memio.read(), buf[-3:])
    490         memio.seek(0)
    491         memio.seek(1, 1)
    492         self.assertEqual(memio.read(), buf[1:])
    493 
    494     def test_unicode(self):
    495         memio = self.ioclass()
    496 
    497         self.assertRaises(TypeError, self.ioclass, "1234567890")
    498         self.assertRaises(TypeError, memio.write, "1234567890")
    499         self.assertRaises(TypeError, memio.writelines, ["1234567890"])
    500 
    501     def test_bytes_array(self):
    502         buf = b"1234567890"
    503         import array
    504         a = array.array('b', list(buf))
    505         memio = self.ioclass(a)
    506         self.assertEqual(memio.getvalue(), buf)
    507         self.assertEqual(memio.write(a), 10)
    508         self.assertEqual(memio.getvalue(), buf)
    509 
    510     def test_issue5449(self):
    511         buf = self.buftype("1234567890")
    512         self.ioclass(initial_bytes=buf)
    513         self.assertRaises(TypeError, self.ioclass, buf, foo=None)
    514 
    515 
    516 class TextIOTestMixin:
    517 
    518     def test_newlines_property(self):
    519         memio = self.ioclass(newline=None)
    520         # The C StringIO decodes newlines in write() calls, but the Python
    521         # implementation only does when reading.  This function forces them to
    522         # be decoded for testing.
    523         def force_decode():
    524             memio.seek(0)
    525             memio.read()
    526         self.assertEqual(memio.newlines, None)
    527         memio.write("a\n")
    528         force_decode()
    529         self.assertEqual(memio.newlines, "\n")
    530         memio.write("b\r\n")
    531         force_decode()
    532         self.assertEqual(memio.newlines, ("\n", "\r\n"))
    533         memio.write("c\rd")
    534         force_decode()
    535         self.assertEqual(memio.newlines, ("\r", "\n", "\r\n"))
    536 
    537     def test_relative_seek(self):
    538         memio = self.ioclass()
    539 
    540         self.assertRaises(OSError, memio.seek, -1, 1)
    541         self.assertRaises(OSError, memio.seek, 3, 1)
    542         self.assertRaises(OSError, memio.seek, -3, 1)
    543         self.assertRaises(OSError, memio.seek, -1, 2)
    544         self.assertRaises(OSError, memio.seek, 1, 1)
    545         self.assertRaises(OSError, memio.seek, 1, 2)
    546 
    547     def test_textio_properties(self):
    548         memio = self.ioclass()
    549 
    550         # These are just dummy values but we nevertheless check them for fear
    551         # of unexpected breakage.
    552         self.assertIsNone(memio.encoding)
    553         self.assertIsNone(memio.errors)
    554         self.assertFalse(memio.line_buffering)
    555 
    556     def test_newline_default(self):
    557         memio = self.ioclass("a\nb\r\nc\rd")
    558         self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
    559         self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
    560 
    561         memio = self.ioclass()
    562         self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
    563         memio.seek(0)
    564         self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
    565         self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
    566 
    567     def test_newline_none(self):
    568         # newline=None
    569         memio = self.ioclass("a\nb\r\nc\rd", newline=None)
    570         self.assertEqual(list(memio), ["a\n", "b\n", "c\n", "d"])
    571         memio.seek(0)
    572         self.assertEqual(memio.read(1), "a")
    573         self.assertEqual(memio.read(2), "\nb")
    574         self.assertEqual(memio.read(2), "\nc")
    575         self.assertEqual(memio.read(1), "\n")
    576         self.assertEqual(memio.getvalue(), "a\nb\nc\nd")
    577 
    578         memio = self.ioclass(newline=None)
    579         self.assertEqual(2, memio.write("a\n"))
    580         self.assertEqual(3, memio.write("b\r\n"))
    581         self.assertEqual(3, memio.write("c\rd"))
    582         memio.seek(0)
    583         self.assertEqual(memio.read(), "a\nb\nc\nd")
    584         self.assertEqual(memio.getvalue(), "a\nb\nc\nd")
    585 
    586         memio = self.ioclass("a\r\nb", newline=None)
    587         self.assertEqual(memio.read(3), "a\nb")
    588 
    589     def test_newline_empty(self):
    590         # newline=""
    591         memio = self.ioclass("a\nb\r\nc\rd", newline="")
    592         self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
    593         memio.seek(0)
    594         self.assertEqual(memio.read(4), "a\nb\r")
    595         self.assertEqual(memio.read(2), "\nc")
    596         self.assertEqual(memio.read(1), "\r")
    597         self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
    598 
    599         memio = self.ioclass(newline="")
    600         self.assertEqual(2, memio.write("a\n"))
    601         self.assertEqual(2, memio.write("b\r"))
    602         self.assertEqual(2, memio.write("\nc"))
    603         self.assertEqual(2, memio.write("\rd"))
    604         memio.seek(0)
    605         self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
    606         self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
    607 
    608     def test_newline_lf(self):
    609         # newline="\n"
    610         memio = self.ioclass("a\nb\r\nc\rd", newline="\n")
    611         self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
    612         self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
    613 
    614         memio = self.ioclass(newline="\n")
    615         self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
    616         memio.seek(0)
    617         self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
    618         self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
    619 
    620     def test_newline_cr(self):
    621         # newline="\r"
    622         memio = self.ioclass("a\nb\r\nc\rd", newline="\r")
    623         self.assertEqual(memio.read(), "a\rb\r\rc\rd")
    624         memio.seek(0)
    625         self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
    626         self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd")
    627 
    628         memio = self.ioclass(newline="\r")
    629         self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
    630         memio.seek(0)
    631         self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
    632         memio.seek(0)
    633         self.assertEqual(memio.readlines(), ["a\r", "b\r", "\r", "c\r", "d"])
    634         self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd")
    635 
    636     def test_newline_crlf(self):
    637         # newline="\r\n"
    638         memio = self.ioclass("a\nb\r\nc\rd", newline="\r\n")
    639         self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd")
    640         memio.seek(0)
    641         self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
    642         memio.seek(0)
    643         self.assertEqual(memio.readlines(), ["a\r\n", "b\r\r\n", "c\rd"])
    644         self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd")
    645 
    646         memio = self.ioclass(newline="\r\n")
    647         self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
    648         memio.seek(0)
    649         self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
    650         self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd")
    651 
    652     def test_issue5265(self):
    653         # StringIO can duplicate newlines in universal newlines mode
    654         memio = self.ioclass("a\r\nb\r\n", newline=None)
    655         self.assertEqual(memio.read(5), "a\nb\n")
    656         self.assertEqual(memio.getvalue(), "a\nb\n")
    657 
    658     def test_newline_argument(self):
    659         self.assertRaises(TypeError, self.ioclass, newline=b"\n")
    660         self.assertRaises(ValueError, self.ioclass, newline="error")
    661         # These should not raise an error
    662         for newline in (None, "", "\n", "\r", "\r\n"):
    663             self.ioclass(newline=newline)
    664 
    665 
    666 class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin,
    667                      TextIOTestMixin, unittest.TestCase):
    668     buftype = str
    669     ioclass = pyio.StringIO
    670     UnsupportedOperation = pyio.UnsupportedOperation
    671     EOF = ""
    672 
    673     def test_lone_surrogates(self):
    674         # Issue #20424
    675         memio = self.ioclass('\ud800')
    676         self.assertEqual(memio.read(), '\ud800')
    677 
    678         memio = self.ioclass()
    679         memio.write('\ud800')
    680         self.assertEqual(memio.getvalue(), '\ud800')
    681 
    682 
    683 class PyStringIOPickleTest(TextIOTestMixin, unittest.TestCase):
    684     """Test if pickle restores properly the internal state of StringIO.
    685     """
    686     buftype = str
    687     UnsupportedOperation = pyio.UnsupportedOperation
    688     EOF = ""
    689 
    690     class ioclass(pyio.StringIO):
    691         def __new__(cls, *args, **kwargs):
    692             return pickle.loads(pickle.dumps(pyio.StringIO(*args, **kwargs)))
    693         def __init__(self, *args, **kwargs):
    694             pass
    695 
    696 
    697 class CBytesIOTest(PyBytesIOTest):
    698     ioclass = io.BytesIO
    699     UnsupportedOperation = io.UnsupportedOperation
    700 
    701     def test_getstate(self):
    702         memio = self.ioclass()
    703         state = memio.__getstate__()
    704         self.assertEqual(len(state), 3)
    705         bytearray(state[0]) # Check if state[0] supports the buffer interface.
    706         self.assertIsInstance(state[1], int)
    707         if state[2] is not None:
    708             self.assertIsInstance(state[2], dict)
    709         memio.close()
    710         self.assertRaises(ValueError, memio.__getstate__)
    711 
    712     def test_setstate(self):
    713         # This checks whether __setstate__ does proper input validation.
    714         memio = self.ioclass()
    715         memio.__setstate__((b"no error", 0, None))
    716         memio.__setstate__((bytearray(b"no error"), 0, None))
    717         memio.__setstate__((b"no error", 0, {'spam': 3}))
    718         self.assertRaises(ValueError, memio.__setstate__, (b"", -1, None))
    719         self.assertRaises(TypeError, memio.__setstate__, ("unicode", 0, None))
    720         self.assertRaises(TypeError, memio.__setstate__, (b"", 0.0, None))
    721         self.assertRaises(TypeError, memio.__setstate__, (b"", 0, 0))
    722         self.assertRaises(TypeError, memio.__setstate__, (b"len-test", 0))
    723         self.assertRaises(TypeError, memio.__setstate__)
    724         self.assertRaises(TypeError, memio.__setstate__, 0)
    725         memio.close()
    726         self.assertRaises(ValueError, memio.__setstate__, (b"closed", 0, None))
    727 
    728     check_sizeof = support.check_sizeof
    729 
    730     @support.cpython_only
    731     def test_sizeof(self):
    732         basesize = support.calcobjsize('P2n2Pn')
    733         check = self.check_sizeof
    734         self.assertEqual(object.__sizeof__(io.BytesIO()), basesize)
    735         check(io.BytesIO(), basesize )
    736         check(io.BytesIO(b'a' * 1000), basesize + sys.getsizeof(b'a' * 1000))
    737 
    738     # Various tests of copy-on-write behaviour for BytesIO.
    739 
    740     def _test_cow_mutation(self, mutation):
    741         # Common code for all BytesIO copy-on-write mutation tests.
    742         imm = b' ' * 1024
    743         old_rc = sys.getrefcount(imm)
    744         memio = self.ioclass(imm)
    745         self.assertEqual(sys.getrefcount(imm), old_rc + 1)
    746         mutation(memio)
    747         self.assertEqual(sys.getrefcount(imm), old_rc)
    748 
    749     @support.cpython_only
    750     def test_cow_truncate(self):
    751         # Ensure truncate causes a copy.
    752         def mutation(memio):
    753             memio.truncate(1)
    754         self._test_cow_mutation(mutation)
    755 
    756     @support.cpython_only
    757     def test_cow_write(self):
    758         # Ensure write that would not cause a resize still results in a copy.
    759         def mutation(memio):
    760             memio.seek(0)
    761             memio.write(b'foo')
    762         self._test_cow_mutation(mutation)
    763 
    764     @support.cpython_only
    765     def test_cow_setstate(self):
    766         # __setstate__ should cause buffer to be released.
    767         memio = self.ioclass(b'foooooo')
    768         state = memio.__getstate__()
    769         def mutation(memio):
    770             memio.__setstate__(state)
    771         self._test_cow_mutation(mutation)
    772 
    773     @support.cpython_only
    774     def test_cow_mutable(self):
    775         # BytesIO should accept only Bytes for copy-on-write sharing, since
    776         # arbitrary buffer-exporting objects like bytearray() aren't guaranteed
    777         # to be immutable.
    778         ba = bytearray(1024)
    779         old_rc = sys.getrefcount(ba)
    780         memio = self.ioclass(ba)
    781         self.assertEqual(sys.getrefcount(ba), old_rc)
    782 
    783 class CStringIOTest(PyStringIOTest):
    784     ioclass = io.StringIO
    785     UnsupportedOperation = io.UnsupportedOperation
    786 
    787     # XXX: For the Python version of io.StringIO, this is highly
    788     # dependent on the encoding used for the underlying buffer.
    789     def test_widechar(self):
    790         buf = self.buftype("\U0002030a\U00020347")
    791         memio = self.ioclass(buf)
    792 
    793         self.assertEqual(memio.getvalue(), buf)
    794         self.assertEqual(memio.write(buf), len(buf))
    795         self.assertEqual(memio.tell(), len(buf))
    796         self.assertEqual(memio.getvalue(), buf)
    797         self.assertEqual(memio.write(buf), len(buf))
    798         self.assertEqual(memio.tell(), len(buf) * 2)
    799         self.assertEqual(memio.getvalue(), buf + buf)
    800 
    801     def test_getstate(self):
    802         memio = self.ioclass()
    803         state = memio.__getstate__()
    804         self.assertEqual(len(state), 4)
    805         self.assertIsInstance(state[0], str)
    806         self.assertIsInstance(state[1], str)
    807         self.assertIsInstance(state[2], int)
    808         if state[3] is not None:
    809             self.assertIsInstance(state[3], dict)
    810         memio.close()
    811         self.assertRaises(ValueError, memio.__getstate__)
    812 
    813     def test_setstate(self):
    814         # This checks whether __setstate__ does proper input validation.
    815         memio = self.ioclass()
    816         memio.__setstate__(("no error", "\n", 0, None))
    817         memio.__setstate__(("no error", "", 0, {'spam': 3}))
    818         self.assertRaises(ValueError, memio.__setstate__, ("", "f", 0, None))
    819         self.assertRaises(ValueError, memio.__setstate__, ("", "", -1, None))
    820         self.assertRaises(TypeError, memio.__setstate__, (b"", "", 0, None))
    821         self.assertRaises(TypeError, memio.__setstate__, ("", b"", 0, None))
    822         self.assertRaises(TypeError, memio.__setstate__, ("", "", 0.0, None))
    823         self.assertRaises(TypeError, memio.__setstate__, ("", "", 0, 0))
    824         self.assertRaises(TypeError, memio.__setstate__, ("len-test", 0))
    825         self.assertRaises(TypeError, memio.__setstate__)
    826         self.assertRaises(TypeError, memio.__setstate__, 0)
    827         memio.close()
    828         self.assertRaises(ValueError, memio.__setstate__, ("closed", "", 0, None))
    829 
    830 
    831 class CStringIOPickleTest(PyStringIOPickleTest):
    832     UnsupportedOperation = io.UnsupportedOperation
    833 
    834     class ioclass(io.StringIO):
    835         def __new__(cls, *args, **kwargs):
    836             return pickle.loads(pickle.dumps(io.StringIO(*args, **kwargs)))
    837         def __init__(self, *args, **kwargs):
    838             pass
    839 
    840 
    841 if __name__ == '__main__':
    842     unittest.main()
    843