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        PickleTestMemIO.__qualname__ = PickleTestMemIO.__name__
380        __main__.PickleTestMemIO = PickleTestMemIO
381        submemio = PickleTestMemIO(buf, 80)
382        submemio.seek(2)
383
384        # We only support pickle protocol 2 and onward since we use extended
385        # __reduce__ API of PEP 307 to provide pickling support.
386        for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
387            for obj in (memio, submemio):
388                obj2 = pickle.loads(pickle.dumps(obj, protocol=proto))
389                self.assertEqual(obj.getvalue(), obj2.getvalue())
390                self.assertEqual(obj.__class__, obj2.__class__)
391                self.assertEqual(obj.foo, obj2.foo)
392                self.assertEqual(obj.tell(), obj2.tell())
393                obj.close()
394                self.assertRaises(ValueError, pickle.dumps, obj, proto)
395        del __main__.PickleTestMemIO
396
397
398class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
399    # Test _pyio.BytesIO; class also inherited for testing C implementation
400
401    UnsupportedOperation = pyio.UnsupportedOperation
402
403    @staticmethod
404    def buftype(s):
405        return s.encode("ascii")
406    ioclass = pyio.BytesIO
407    EOF = b""
408
409    def test_read1(self):
410        buf = self.buftype("1234567890")
411        memio = self.ioclass(buf)
412
413        self.assertRaises(TypeError, memio.read1)
414        self.assertEqual(memio.read(), buf)
415
416    def test_readinto(self):
417        buf = self.buftype("1234567890")
418        memio = self.ioclass(buf)
419
420        b = bytearray(b"hello")
421        self.assertEqual(memio.readinto(b), 5)
422        self.assertEqual(b, b"12345")
423        self.assertEqual(memio.readinto(b), 5)
424        self.assertEqual(b, b"67890")
425        self.assertEqual(memio.readinto(b), 0)
426        self.assertEqual(b, b"67890")
427        b = bytearray(b"hello world")
428        memio.seek(0)
429        self.assertEqual(memio.readinto(b), 10)
430        self.assertEqual(b, b"1234567890d")
431        b = bytearray(b"")
432        memio.seek(0)
433        self.assertEqual(memio.readinto(b), 0)
434        self.assertEqual(b, b"")
435        self.assertRaises(TypeError, memio.readinto, '')
436        import array
437        a = array.array(b'b', b"hello world")
438        memio = self.ioclass(buf)
439        memio.readinto(a)
440        self.assertEqual(a.tostring(), b"1234567890d")
441        memio.close()
442        self.assertRaises(ValueError, memio.readinto, b)
443        memio = self.ioclass(b"123")
444        b = bytearray()
445        memio.seek(42)
446        memio.readinto(b)
447        self.assertEqual(b, b"")
448
449    def test_relative_seek(self):
450        buf = self.buftype("1234567890")
451        memio = self.ioclass(buf)
452
453        self.assertEqual(memio.seek(-1, 1), 0)
454        self.assertEqual(memio.seek(3, 1), 3)
455        self.assertEqual(memio.seek(-4, 1), 0)
456        self.assertEqual(memio.seek(-1, 2), 9)
457        self.assertEqual(memio.seek(1, 1), 10)
458        self.assertEqual(memio.seek(1, 2), 11)
459        memio.seek(-3, 2)
460        self.assertEqual(memio.read(), buf[-3:])
461        memio.seek(0)
462        memio.seek(1, 1)
463        self.assertEqual(memio.read(), buf[1:])
464
465    def test_unicode(self):
466        memio = self.ioclass()
467
468        self.assertRaises(TypeError, self.ioclass, "1234567890")
469        self.assertRaises(TypeError, memio.write, "1234567890")
470        self.assertRaises(TypeError, memio.writelines, ["1234567890"])
471
472    def test_bytes_array(self):
473        buf = b"1234567890"
474        import array
475        a = array.array(b'b', buf)
476        memio = self.ioclass(a)
477        self.assertEqual(memio.getvalue(), buf)
478        self.assertEqual(memio.write(a), 10)
479        self.assertEqual(memio.getvalue(), buf)
480
481    def test_issue5449(self):
482        buf = self.buftype("1234567890")
483        self.ioclass(initial_bytes=buf)
484        self.assertRaises(TypeError, self.ioclass, buf, foo=None)
485
486
487class TextIOTestMixin:
488
489    def test_newlines_property(self):
490        memio = self.ioclass(newline=None)
491        # The C StringIO decodes newlines in write() calls, but the Python
492        # implementation only does when reading.  This function forces them to
493        # be decoded for testing.
494        def force_decode():
495            memio.seek(0)
496            memio.read()
497        self.assertEqual(memio.newlines, None)
498        memio.write("a\n")
499        force_decode()
500        self.assertEqual(memio.newlines, "\n")
501        memio.write("b\r\n")
502        force_decode()
503        self.assertEqual(memio.newlines, ("\n", "\r\n"))
504        memio.write("c\rd")
505        force_decode()
506        self.assertEqual(memio.newlines, ("\r", "\n", "\r\n"))
507
508    def test_relative_seek(self):
509        memio = self.ioclass()
510
511        self.assertRaises(IOError, memio.seek, -1, 1)
512        self.assertRaises(IOError, memio.seek, 3, 1)
513        self.assertRaises(IOError, memio.seek, -3, 1)
514        self.assertRaises(IOError, memio.seek, -1, 2)
515        self.assertRaises(IOError, memio.seek, 1, 1)
516        self.assertRaises(IOError, memio.seek, 1, 2)
517
518    def test_textio_properties(self):
519        memio = self.ioclass()
520
521        # These are just dummy values but we nevertheless check them for fear
522        # of unexpected breakage.
523        self.assertIsNone(memio.encoding)
524        self.assertIsNone(memio.errors)
525        self.assertFalse(memio.line_buffering)
526
527    def test_newline_default(self):
528        memio = self.ioclass("a\nb\r\nc\rd")
529        self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
530        self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
531
532        memio = self.ioclass()
533        self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
534        memio.seek(0)
535        self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
536        self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
537
538    def test_newline_none(self):
539        # newline=None
540        memio = self.ioclass("a\nb\r\nc\rd", newline=None)
541        self.assertEqual(list(memio), ["a\n", "b\n", "c\n", "d"])
542        memio.seek(0)
543        self.assertEqual(memio.read(1), "a")
544        self.assertEqual(memio.read(2), "\nb")
545        self.assertEqual(memio.read(2), "\nc")
546        self.assertEqual(memio.read(1), "\n")
547        self.assertEqual(memio.getvalue(), "a\nb\nc\nd")
548
549        memio = self.ioclass(newline=None)
550        self.assertEqual(2, memio.write("a\n"))
551        self.assertEqual(3, memio.write("b\r\n"))
552        self.assertEqual(3, memio.write("c\rd"))
553        memio.seek(0)
554        self.assertEqual(memio.read(), "a\nb\nc\nd")
555        self.assertEqual(memio.getvalue(), "a\nb\nc\nd")
556
557        memio = self.ioclass("a\r\nb", newline=None)
558        self.assertEqual(memio.read(3), "a\nb")
559
560    def test_newline_empty(self):
561        # newline=""
562        memio = self.ioclass("a\nb\r\nc\rd", newline="")
563        self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
564        memio.seek(0)
565        self.assertEqual(memio.read(4), "a\nb\r")
566        self.assertEqual(memio.read(2), "\nc")
567        self.assertEqual(memio.read(1), "\r")
568        self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
569
570        memio = self.ioclass(newline="")
571        self.assertEqual(2, memio.write("a\n"))
572        self.assertEqual(2, memio.write("b\r"))
573        self.assertEqual(2, memio.write("\nc"))
574        self.assertEqual(2, memio.write("\rd"))
575        memio.seek(0)
576        self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
577        self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
578
579    def test_newline_lf(self):
580        # newline="\n"
581        memio = self.ioclass("a\nb\r\nc\rd", newline="\n")
582        self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
583        self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
584
585        memio = self.ioclass(newline="\n")
586        self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
587        memio.seek(0)
588        self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
589        self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
590
591    def test_newline_cr(self):
592        # newline="\r"
593        memio = self.ioclass("a\nb\r\nc\rd", newline="\r")
594        self.assertEqual(memio.read(), "a\rb\r\rc\rd")
595        memio.seek(0)
596        self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
597        self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd")
598
599        memio = self.ioclass(newline="\r")
600        self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
601        memio.seek(0)
602        self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
603        memio.seek(0)
604        self.assertEqual(memio.readlines(), ["a\r", "b\r", "\r", "c\r", "d"])
605        self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd")
606
607    def test_newline_crlf(self):
608        # newline="\r\n"
609        memio = self.ioclass("a\nb\r\nc\rd", newline="\r\n")
610        self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd")
611        memio.seek(0)
612        self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
613        memio.seek(0)
614        self.assertEqual(memio.readlines(), ["a\r\n", "b\r\r\n", "c\rd"])
615        self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd")
616
617        memio = self.ioclass(newline="\r\n")
618        self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
619        memio.seek(0)
620        self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
621        self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd")
622
623    def test_issue5265(self):
624        # StringIO can duplicate newlines in universal newlines mode
625        memio = self.ioclass("a\r\nb\r\n", newline=None)
626        self.assertEqual(memio.read(5), "a\nb\n")
627        self.assertEqual(memio.getvalue(), "a\nb\n")
628
629
630class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin,
631                     TextIOTestMixin, unittest.TestCase):
632    buftype = unicode
633    ioclass = pyio.StringIO
634    UnsupportedOperation = pyio.UnsupportedOperation
635    EOF = ""
636
637    def test_lone_surrogates(self):
638        # Issue #20424
639        surrogate = unichr(0xd800)
640        memio = self.ioclass(surrogate)
641        self.assertEqual(memio.read(), surrogate)
642
643        memio = self.ioclass()
644        memio.write(surrogate)
645        self.assertEqual(memio.getvalue(), surrogate)
646
647
648class PyStringIOPickleTest(TextIOTestMixin, unittest.TestCase):
649    """Test if pickle restores properly the internal state of StringIO.
650    """
651    buftype = unicode
652    UnsupportedOperation = pyio.UnsupportedOperation
653    EOF = ""
654
655    class ioclass(pyio.StringIO):
656        def __new__(cls, *args, **kwargs):
657            return pickle.loads(pickle.dumps(pyio.StringIO(*args, **kwargs)))
658        def __init__(self, *args, **kwargs):
659            pass
660
661
662class CBytesIOTest(PyBytesIOTest):
663    ioclass = io.BytesIO
664    UnsupportedOperation = io.UnsupportedOperation
665
666    test_bytes_array = unittest.skip(
667        "array.array() does not have the new buffer API"
668    )(PyBytesIOTest.test_bytes_array)
669
670
671    def test_getstate(self):
672        memio = self.ioclass()
673        state = memio.__getstate__()
674        self.assertEqual(len(state), 3)
675        bytearray(state[0]) # Check if state[0] supports the buffer interface.
676        self.assertIsInstance(state[1], int)
677        if state[2] is not None:
678            self.assertIsInstance(state[2], dict)
679        memio.close()
680        self.assertRaises(ValueError, memio.__getstate__)
681
682    def test_setstate(self):
683        # This checks whether __setstate__ does proper input validation.
684        memio = self.ioclass()
685        memio.__setstate__((b"no error", 0, None))
686        memio.__setstate__((bytearray(b"no error"), 0, None))
687        memio.__setstate__((b"no error", 0, {'spam': 3}))
688        self.assertRaises(ValueError, memio.__setstate__, (b"", -1, None))
689        self.assertRaises(TypeError, memio.__setstate__, ("unicode", 0, None))
690        self.assertRaises(TypeError, memio.__setstate__, (b"", 0.0, None))
691        self.assertRaises(TypeError, memio.__setstate__, (b"", 0, 0))
692        self.assertRaises(TypeError, memio.__setstate__, (b"len-test", 0))
693        self.assertRaises(TypeError, memio.__setstate__)
694        self.assertRaises(TypeError, memio.__setstate__, 0)
695        memio.close()
696        self.assertRaises(ValueError, memio.__setstate__, (b"closed", 0, None))
697
698    check_sizeof = support.check_sizeof
699
700    @support.cpython_only
701    def test_sizeof(self):
702        basesize = support.calcobjsize(b'P2PP2P')
703        check = self.check_sizeof
704        self.assertEqual(object.__sizeof__(io.BytesIO()), basesize)
705        check(io.BytesIO(), basesize )
706        check(io.BytesIO(b'a'), basesize + 1 + 1 )
707        check(io.BytesIO(b'a' * 1000), basesize + 1000 + 1 )
708
709class CStringIOTest(PyStringIOTest):
710    ioclass = io.StringIO
711    UnsupportedOperation = io.UnsupportedOperation
712
713    # XXX: For the Python version of io.StringIO, this is highly
714    # dependent on the encoding used for the underlying buffer.
715    def test_widechar(self):
716        buf = self.buftype("\U0002030a\U00020347")
717        memio = self.ioclass(buf)
718
719        self.assertEqual(memio.getvalue(), buf)
720        self.assertEqual(memio.write(buf), len(buf))
721        self.assertEqual(memio.tell(), len(buf))
722        self.assertEqual(memio.getvalue(), buf)
723        self.assertEqual(memio.write(buf), len(buf))
724        self.assertEqual(memio.tell(), len(buf) * 2)
725        self.assertEqual(memio.getvalue(), buf + buf)
726
727    def test_getstate(self):
728        memio = self.ioclass()
729        state = memio.__getstate__()
730        self.assertEqual(len(state), 4)
731        self.assertIsInstance(state[0], unicode)
732        self.assertIsInstance(state[1], str)
733        self.assertIsInstance(state[2], int)
734        if state[3] is not None:
735            self.assertIsInstance(state[3], dict)
736        memio.close()
737        self.assertRaises(ValueError, memio.__getstate__)
738
739    def test_setstate(self):
740        # This checks whether __setstate__ does proper input validation.
741        memio = self.ioclass()
742        memio.__setstate__(("no error", "\n", 0, None))
743        memio.__setstate__(("no error", "", 0, {'spam': 3}))
744        self.assertRaises(ValueError, memio.__setstate__, ("", "f", 0, None))
745        self.assertRaises(ValueError, memio.__setstate__, ("", "", -1, None))
746        self.assertRaises(TypeError, memio.__setstate__, (b"", "", 0, None))
747        # trunk is more tolerant than py3k on the type of the newline param
748        #self.assertRaises(TypeError, memio.__setstate__, ("", b"", 0, None))
749        self.assertRaises(TypeError, memio.__setstate__, ("", "", 0.0, None))
750        self.assertRaises(TypeError, memio.__setstate__, ("", "", 0, 0))
751        self.assertRaises(TypeError, memio.__setstate__, ("len-test", 0))
752        self.assertRaises(TypeError, memio.__setstate__)
753        self.assertRaises(TypeError, memio.__setstate__, 0)
754        memio.close()
755        self.assertRaises(ValueError, memio.__setstate__, ("closed", "", 0, None))
756
757
758class CStringIOPickleTest(PyStringIOPickleTest):
759    UnsupportedOperation = io.UnsupportedOperation
760
761    class ioclass(io.StringIO):
762        def __new__(cls, *args, **kwargs):
763            return pickle.loads(pickle.dumps(io.StringIO(*args, **kwargs),
764                                             protocol=2))
765        def __init__(self, *args, **kwargs):
766            pass
767
768
769def test_main():
770    tests = [PyBytesIOTest, PyStringIOTest, CBytesIOTest, CStringIOTest,
771             PyStringIOPickleTest, CStringIOPickleTest]
772    support.run_unittest(*tests)
773
774if __name__ == '__main__':
775    test_main()
776