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