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