blob: 9a2461dea68b83b435c0b7b45941956c61938d5c [file] [log] [blame]
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001"""Unit tests for memory-based file-like objects.
2StringIO -- for unicode strings
3BytesIO -- for bytes
4"""
5
6import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00007from test import support
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00008
9import io
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000010import _pyio as pyio
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +000011import pickle
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000012
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000013class MemorySeekTestMixin:
14
15 def testInit(self):
16 buf = self.buftype("1234567890")
17 bytesIo = self.ioclass(buf)
18
19 def testRead(self):
20 buf = self.buftype("1234567890")
21 bytesIo = self.ioclass(buf)
22
Ezio Melottib3aedd42010-11-20 19:04:17 +000023 self.assertEqual(buf[:1], bytesIo.read(1))
24 self.assertEqual(buf[1:5], bytesIo.read(4))
25 self.assertEqual(buf[5:], bytesIo.read(900))
26 self.assertEqual(self.EOF, bytesIo.read())
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000027
28 def testReadNoArgs(self):
29 buf = self.buftype("1234567890")
30 bytesIo = self.ioclass(buf)
31
Ezio Melottib3aedd42010-11-20 19:04:17 +000032 self.assertEqual(buf, bytesIo.read())
33 self.assertEqual(self.EOF, bytesIo.read())
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000034
35 def testSeek(self):
36 buf = self.buftype("1234567890")
37 bytesIo = self.ioclass(buf)
38
39 bytesIo.read(5)
40 bytesIo.seek(0)
Ezio Melottib3aedd42010-11-20 19:04:17 +000041 self.assertEqual(buf, bytesIo.read())
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000042
43 bytesIo.seek(3)
Ezio Melottib3aedd42010-11-20 19:04:17 +000044 self.assertEqual(buf[3:], bytesIo.read())
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000045 self.assertRaises(TypeError, bytesIo.seek, 0.0)
46
47 def testTell(self):
48 buf = self.buftype("1234567890")
49 bytesIo = self.ioclass(buf)
50
Ezio Melottib3aedd42010-11-20 19:04:17 +000051 self.assertEqual(0, bytesIo.tell())
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000052 bytesIo.seek(5)
Ezio Melottib3aedd42010-11-20 19:04:17 +000053 self.assertEqual(5, bytesIo.tell())
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000054 bytesIo.seek(10000)
Ezio Melottib3aedd42010-11-20 19:04:17 +000055 self.assertEqual(10000, bytesIo.tell())
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000056
57
58class MemoryTestMixin:
59
Benjamin Petersond2e0c792009-05-01 20:40:59 +000060 def test_detach(self):
61 buf = self.ioclass()
62 self.assertRaises(self.UnsupportedOperation, buf.detach)
63
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000064 def write_ops(self, f, t):
65 self.assertEqual(f.write(t("blah.")), 5)
66 self.assertEqual(f.seek(0), 0)
67 self.assertEqual(f.write(t("Hello.")), 6)
68 self.assertEqual(f.tell(), 6)
69 self.assertEqual(f.seek(5), 5)
70 self.assertEqual(f.tell(), 5)
71 self.assertEqual(f.write(t(" world\n\n\n")), 9)
72 self.assertEqual(f.seek(0), 0)
73 self.assertEqual(f.write(t("h")), 1)
74 self.assertEqual(f.truncate(12), 12)
Antoine Pitrou905a2ff2010-01-31 22:47:27 +000075 self.assertEqual(f.tell(), 1)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000076
77 def test_write(self):
78 buf = self.buftype("hello world\n")
79 memio = self.ioclass(buf)
80
81 self.write_ops(memio, self.buftype)
82 self.assertEqual(memio.getvalue(), buf)
83 memio = self.ioclass()
84 self.write_ops(memio, self.buftype)
85 self.assertEqual(memio.getvalue(), buf)
86 self.assertRaises(TypeError, memio.write, None)
87 memio.close()
88 self.assertRaises(ValueError, memio.write, self.buftype(""))
89
90 def test_writelines(self):
91 buf = self.buftype("1234567890")
92 memio = self.ioclass()
93
94 self.assertEqual(memio.writelines([buf] * 100), None)
95 self.assertEqual(memio.getvalue(), buf * 100)
96 memio.writelines([])
97 self.assertEqual(memio.getvalue(), buf * 100)
98 memio = self.ioclass()
99 self.assertRaises(TypeError, memio.writelines, [buf] + [1])
100 self.assertEqual(memio.getvalue(), buf)
101 self.assertRaises(TypeError, memio.writelines, None)
102 memio.close()
103 self.assertRaises(ValueError, memio.writelines, [])
104
105 def test_writelines_error(self):
106 memio = self.ioclass()
107 def error_gen():
108 yield self.buftype('spam')
109 raise KeyboardInterrupt
110
111 self.assertRaises(KeyboardInterrupt, memio.writelines, error_gen())
112
113 def test_truncate(self):
114 buf = self.buftype("1234567890")
115 memio = self.ioclass(buf)
116
117 self.assertRaises(ValueError, memio.truncate, -1)
118 memio.seek(6)
119 self.assertEqual(memio.truncate(), 6)
120 self.assertEqual(memio.getvalue(), buf[:6])
121 self.assertEqual(memio.truncate(4), 4)
122 self.assertEqual(memio.getvalue(), buf[:4])
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000123 self.assertEqual(memio.tell(), 6)
124 memio.seek(0, 2)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000125 memio.write(buf)
126 self.assertEqual(memio.getvalue(), buf[:4] + buf)
127 pos = memio.tell()
128 self.assertEqual(memio.truncate(None), pos)
129 self.assertEqual(memio.tell(), pos)
130 self.assertRaises(TypeError, memio.truncate, '0')
131 memio.close()
132 self.assertRaises(ValueError, memio.truncate, 0)
133
134 def test_init(self):
135 buf = self.buftype("1234567890")
136 memio = self.ioclass(buf)
137 self.assertEqual(memio.getvalue(), buf)
138 memio = self.ioclass(None)
139 self.assertEqual(memio.getvalue(), self.EOF)
140 memio.__init__(buf * 2)
141 self.assertEqual(memio.getvalue(), buf * 2)
142 memio.__init__(buf)
143 self.assertEqual(memio.getvalue(), buf)
Alexandre Vassalottid2bb18b2009-07-22 03:07:33 +0000144 self.assertRaises(TypeError, memio.__init__, [])
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000145
146 def test_read(self):
147 buf = self.buftype("1234567890")
148 memio = self.ioclass(buf)
149
150 self.assertEqual(memio.read(0), self.EOF)
151 self.assertEqual(memio.read(1), buf[:1])
152 self.assertEqual(memio.read(4), buf[1:5])
153 self.assertEqual(memio.read(900), buf[5:])
154 self.assertEqual(memio.read(), self.EOF)
155 memio.seek(0)
156 self.assertEqual(memio.read(), buf)
157 self.assertEqual(memio.read(), self.EOF)
158 self.assertEqual(memio.tell(), 10)
159 memio.seek(0)
160 self.assertEqual(memio.read(-1), buf)
161 memio.seek(0)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000162 self.assertEqual(type(memio.read()), type(buf))
Alexandre Vassalotti4833b3c2008-05-06 23:47:23 +0000163 memio.seek(100)
164 self.assertEqual(type(memio.read()), type(buf))
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000165 memio.seek(0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000166 self.assertEqual(memio.read(None), buf)
167 self.assertRaises(TypeError, memio.read, '')
168 memio.close()
169 self.assertRaises(ValueError, memio.read)
170
171 def test_readline(self):
172 buf = self.buftype("1234567890\n")
173 memio = self.ioclass(buf * 2)
174
175 self.assertEqual(memio.readline(0), self.EOF)
176 self.assertEqual(memio.readline(), buf)
177 self.assertEqual(memio.readline(), buf)
178 self.assertEqual(memio.readline(), self.EOF)
179 memio.seek(0)
180 self.assertEqual(memio.readline(5), buf[:5])
181 self.assertEqual(memio.readline(5), buf[5:10])
182 self.assertEqual(memio.readline(5), buf[10:15])
183 memio.seek(0)
184 self.assertEqual(memio.readline(-1), buf)
185 memio.seek(0)
186 self.assertEqual(memio.readline(0), self.EOF)
187
188 buf = self.buftype("1234567890\n")
189 memio = self.ioclass((buf * 3)[:-1])
190 self.assertEqual(memio.readline(), buf)
191 self.assertEqual(memio.readline(), buf)
192 self.assertEqual(memio.readline(), buf[:-1])
193 self.assertEqual(memio.readline(), self.EOF)
194 memio.seek(0)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000195 self.assertEqual(type(memio.readline()), type(buf))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000196 self.assertEqual(memio.readline(), buf)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000197 self.assertRaises(TypeError, memio.readline, '')
198 memio.close()
199 self.assertRaises(ValueError, memio.readline)
200
201 def test_readlines(self):
202 buf = self.buftype("1234567890\n")
203 memio = self.ioclass(buf * 10)
204
205 self.assertEqual(memio.readlines(), [buf] * 10)
206 memio.seek(5)
207 self.assertEqual(memio.readlines(), [buf[5:]] + [buf] * 9)
208 memio.seek(0)
209 self.assertEqual(memio.readlines(15), [buf] * 2)
210 memio.seek(0)
211 self.assertEqual(memio.readlines(-1), [buf] * 10)
212 memio.seek(0)
213 self.assertEqual(memio.readlines(0), [buf] * 10)
214 memio.seek(0)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000215 self.assertEqual(type(memio.readlines()[0]), type(buf))
216 memio.seek(0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000217 self.assertEqual(memio.readlines(None), [buf] * 10)
218 self.assertRaises(TypeError, memio.readlines, '')
219 memio.close()
220 self.assertRaises(ValueError, memio.readlines)
221
222 def test_iterator(self):
223 buf = self.buftype("1234567890\n")
224 memio = self.ioclass(buf * 10)
225
226 self.assertEqual(iter(memio), memio)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000227 self.assertTrue(hasattr(memio, '__iter__'))
228 self.assertTrue(hasattr(memio, '__next__'))
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000229 i = 0
230 for line in memio:
231 self.assertEqual(line, buf)
232 i += 1
233 self.assertEqual(i, 10)
234 memio.seek(0)
235 i = 0
236 for line in memio:
237 self.assertEqual(line, buf)
238 i += 1
239 self.assertEqual(i, 10)
240 memio = self.ioclass(buf * 2)
241 memio.close()
242 self.assertRaises(ValueError, memio.__next__)
243
244 def test_getvalue(self):
245 buf = self.buftype("1234567890")
246 memio = self.ioclass(buf)
247
248 self.assertEqual(memio.getvalue(), buf)
249 memio.read()
250 self.assertEqual(memio.getvalue(), buf)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000251 self.assertEqual(type(memio.getvalue()), type(buf))
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000252 memio = self.ioclass(buf * 1000)
253 self.assertEqual(memio.getvalue()[-3:], self.buftype("890"))
254 memio = self.ioclass(buf)
255 memio.close()
256 self.assertRaises(ValueError, memio.getvalue)
257
258 def test_seek(self):
259 buf = self.buftype("1234567890")
260 memio = self.ioclass(buf)
261
262 memio.read(5)
263 self.assertRaises(ValueError, memio.seek, -1)
264 self.assertRaises(ValueError, memio.seek, 1, -1)
265 self.assertRaises(ValueError, memio.seek, 1, 3)
266 self.assertEqual(memio.seek(0), 0)
267 self.assertEqual(memio.seek(0, 0), 0)
268 self.assertEqual(memio.read(), buf)
269 self.assertEqual(memio.seek(3), 3)
270 self.assertEqual(memio.seek(0, 1), 3)
271 self.assertEqual(memio.read(), buf[3:])
272 self.assertEqual(memio.seek(len(buf)), len(buf))
273 self.assertEqual(memio.read(), self.EOF)
274 memio.seek(len(buf) + 1)
275 self.assertEqual(memio.read(), self.EOF)
276 self.assertEqual(memio.seek(0, 2), len(buf))
277 self.assertEqual(memio.read(), self.EOF)
278 memio.close()
279 self.assertRaises(ValueError, memio.seek, 0)
280
281 def test_overseek(self):
282 buf = self.buftype("1234567890")
283 memio = self.ioclass(buf)
284
285 self.assertEqual(memio.seek(len(buf) + 1), 11)
286 self.assertEqual(memio.read(), self.EOF)
287 self.assertEqual(memio.tell(), 11)
288 self.assertEqual(memio.getvalue(), buf)
289 memio.write(self.EOF)
290 self.assertEqual(memio.getvalue(), buf)
291 memio.write(buf)
292 self.assertEqual(memio.getvalue(), buf + self.buftype('\0') + buf)
293
294 def test_tell(self):
295 buf = self.buftype("1234567890")
296 memio = self.ioclass(buf)
297
298 self.assertEqual(memio.tell(), 0)
299 memio.seek(5)
300 self.assertEqual(memio.tell(), 5)
301 memio.seek(10000)
302 self.assertEqual(memio.tell(), 10000)
303 memio.close()
304 self.assertRaises(ValueError, memio.tell)
305
306 def test_flush(self):
307 buf = self.buftype("1234567890")
308 memio = self.ioclass(buf)
309
310 self.assertEqual(memio.flush(), None)
311
312 def test_flags(self):
313 memio = self.ioclass()
314
315 self.assertEqual(memio.writable(), True)
316 self.assertEqual(memio.readable(), True)
317 self.assertEqual(memio.seekable(), True)
318 self.assertEqual(memio.isatty(), False)
319 self.assertEqual(memio.closed, False)
320 memio.close()
Antoine Pitrou1d857452012-09-05 20:11:49 +0200321 self.assertRaises(ValueError, memio.writable)
322 self.assertRaises(ValueError, memio.readable)
323 self.assertRaises(ValueError, memio.seekable)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000324 self.assertRaises(ValueError, memio.isatty)
325 self.assertEqual(memio.closed, True)
326
327 def test_subclassing(self):
328 buf = self.buftype("1234567890")
329 def test1():
330 class MemIO(self.ioclass):
331 pass
332 m = MemIO(buf)
333 return m.getvalue()
334 def test2():
335 class MemIO(self.ioclass):
336 def __init__(me, a, b):
337 self.ioclass.__init__(me, a)
338 m = MemIO(buf, None)
339 return m.getvalue()
340 self.assertEqual(test1(), buf)
341 self.assertEqual(test2(), buf)
342
Alexandre Vassalottifc477042009-07-22 02:24:49 +0000343 def test_instance_dict_leak(self):
344 # Test case for issue #6242.
345 # This will be caught by regrtest.py -R if this leak.
346 for _ in range(100):
347 memio = self.ioclass()
348 memio.foo = 1
349
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000350 def test_pickling(self):
351 buf = self.buftype("1234567890")
352 memio = self.ioclass(buf)
353 memio.foo = 42
354 memio.seek(2)
355
356 class PickleTestMemIO(self.ioclass):
357 def __init__(me, initvalue, foo):
358 self.ioclass.__init__(me, initvalue)
359 me.foo = foo
360 # __getnewargs__ is undefined on purpose. This checks that PEP 307
361 # is used to provide pickling support.
362
363 # Pickle expects the class to be on the module level. Here we use a
364 # little hack to allow the PickleTestMemIO class to derive from
365 # self.ioclass without having to define all combinations explictly on
366 # the module-level.
367 import __main__
368 PickleTestMemIO.__module__ = '__main__'
Serhiy Storchakabad12572014-12-15 14:03:42 +0200369 PickleTestMemIO.__qualname__ = PickleTestMemIO.__name__
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000370 __main__.PickleTestMemIO = PickleTestMemIO
371 submemio = PickleTestMemIO(buf, 80)
372 submemio.seek(2)
373
374 # We only support pickle protocol 2 and onward since we use extended
375 # __reduce__ API of PEP 307 to provide pickling support.
Serhiy Storchakabad12572014-12-15 14:03:42 +0200376 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000377 for obj in (memio, submemio):
378 obj2 = pickle.loads(pickle.dumps(obj, protocol=proto))
379 self.assertEqual(obj.getvalue(), obj2.getvalue())
380 self.assertEqual(obj.__class__, obj2.__class__)
381 self.assertEqual(obj.foo, obj2.foo)
382 self.assertEqual(obj.tell(), obj2.tell())
Alexandre Vassalotti6eea8182013-04-14 00:56:39 -0700383 obj2.close()
384 self.assertRaises(ValueError, pickle.dumps, obj2, proto)
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000385 del __main__.PickleTestMemIO
386
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000387
Antoine Pitrou972ee132010-09-06 18:48:21 +0000388class BytesIOMixin:
389
390 def test_getbuffer(self):
391 memio = self.ioclass(b"1234567890")
392 buf = memio.getbuffer()
393 self.assertEqual(bytes(buf), b"1234567890")
394 memio.seek(5)
395 buf = memio.getbuffer()
396 self.assertEqual(bytes(buf), b"1234567890")
397 # Trying to change the size of the BytesIO while a buffer is exported
398 # raises a BufferError.
399 self.assertRaises(BufferError, memio.write, b'x' * 100)
400 self.assertRaises(BufferError, memio.truncate)
Serhiy Storchakac057c382015-02-03 02:00:18 +0200401 self.assertRaises(BufferError, memio.close)
402 self.assertFalse(memio.closed)
Antoine Pitrou972ee132010-09-06 18:48:21 +0000403 # Mutating the buffer updates the BytesIO
404 buf[3:6] = b"abc"
405 self.assertEqual(bytes(buf), b"123abc7890")
406 self.assertEqual(memio.getvalue(), b"123abc7890")
Serhiy Storchakac057c382015-02-03 02:00:18 +0200407 # After the buffer gets released, we can resize and close the BytesIO
408 # again
Antoine Pitrou972ee132010-09-06 18:48:21 +0000409 del buf
410 support.gc_collect()
411 memio.truncate()
Serhiy Storchakac057c382015-02-03 02:00:18 +0200412 memio.close()
413 self.assertRaises(ValueError, memio.getbuffer)
Antoine Pitrou972ee132010-09-06 18:48:21 +0000414
415
416class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin,
417 BytesIOMixin, unittest.TestCase):
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000418
419 UnsupportedOperation = pyio.UnsupportedOperation
420
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000421 @staticmethod
422 def buftype(s):
423 return s.encode("ascii")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000424 ioclass = pyio.BytesIO
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000425 EOF = b""
426
427 def test_read1(self):
428 buf = self.buftype("1234567890")
429 memio = self.ioclass(buf)
430
431 self.assertRaises(TypeError, memio.read1)
432 self.assertEqual(memio.read(), buf)
433
434 def test_readinto(self):
435 buf = self.buftype("1234567890")
436 memio = self.ioclass(buf)
437
438 b = bytearray(b"hello")
439 self.assertEqual(memio.readinto(b), 5)
440 self.assertEqual(b, b"12345")
441 self.assertEqual(memio.readinto(b), 5)
442 self.assertEqual(b, b"67890")
443 self.assertEqual(memio.readinto(b), 0)
444 self.assertEqual(b, b"67890")
445 b = bytearray(b"hello world")
446 memio.seek(0)
447 self.assertEqual(memio.readinto(b), 10)
448 self.assertEqual(b, b"1234567890d")
449 b = bytearray(b"")
450 memio.seek(0)
451 self.assertEqual(memio.readinto(b), 0)
452 self.assertEqual(b, b"")
453 self.assertRaises(TypeError, memio.readinto, '')
454 import array
455 a = array.array('b', b"hello world")
456 memio = self.ioclass(buf)
457 memio.readinto(a)
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000458 self.assertEqual(a.tobytes(), b"1234567890d")
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000459 memio.close()
460 self.assertRaises(ValueError, memio.readinto, b)
Benjamin Petersonfa735552010-11-20 17:24:04 +0000461 memio = self.ioclass(b"123")
462 b = bytearray()
463 memio.seek(42)
464 memio.readinto(b)
465 self.assertEqual(b, b"")
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000466
467 def test_relative_seek(self):
468 buf = self.buftype("1234567890")
469 memio = self.ioclass(buf)
470
471 self.assertEqual(memio.seek(-1, 1), 0)
472 self.assertEqual(memio.seek(3, 1), 3)
473 self.assertEqual(memio.seek(-4, 1), 0)
474 self.assertEqual(memio.seek(-1, 2), 9)
475 self.assertEqual(memio.seek(1, 1), 10)
476 self.assertEqual(memio.seek(1, 2), 11)
477 memio.seek(-3, 2)
478 self.assertEqual(memio.read(), buf[-3:])
479 memio.seek(0)
480 memio.seek(1, 1)
481 self.assertEqual(memio.read(), buf[1:])
482
483 def test_unicode(self):
484 memio = self.ioclass()
485
486 self.assertRaises(TypeError, self.ioclass, "1234567890")
487 self.assertRaises(TypeError, memio.write, "1234567890")
488 self.assertRaises(TypeError, memio.writelines, ["1234567890"])
489
490 def test_bytes_array(self):
491 buf = b"1234567890"
492 import array
493 a = array.array('b', list(buf))
494 memio = self.ioclass(a)
495 self.assertEqual(memio.getvalue(), buf)
496 self.assertEqual(memio.write(a), 10)
497 self.assertEqual(memio.getvalue(), buf)
498
Alexandre Vassalottiba5c7432009-08-04 23:19:13 +0000499 def test_issue5449(self):
500 buf = self.buftype("1234567890")
501 self.ioclass(initial_bytes=buf)
502 self.assertRaises(TypeError, self.ioclass, buf, foo=None)
503
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000504
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000505class TextIOTestMixin:
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000506
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000507 def test_newlines_property(self):
508 memio = self.ioclass(newline=None)
509 # The C StringIO decodes newlines in write() calls, but the Python
510 # implementation only does when reading. This function forces them to
511 # be decoded for testing.
512 def force_decode():
513 memio.seek(0)
514 memio.read()
515 self.assertEqual(memio.newlines, None)
516 memio.write("a\n")
517 force_decode()
518 self.assertEqual(memio.newlines, "\n")
519 memio.write("b\r\n")
520 force_decode()
521 self.assertEqual(memio.newlines, ("\n", "\r\n"))
522 memio.write("c\rd")
523 force_decode()
524 self.assertEqual(memio.newlines, ("\r", "\n", "\r\n"))
525
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000526 def test_relative_seek(self):
527 memio = self.ioclass()
528
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200529 self.assertRaises(OSError, memio.seek, -1, 1)
530 self.assertRaises(OSError, memio.seek, 3, 1)
531 self.assertRaises(OSError, memio.seek, -3, 1)
532 self.assertRaises(OSError, memio.seek, -1, 2)
533 self.assertRaises(OSError, memio.seek, 1, 1)
534 self.assertRaises(OSError, memio.seek, 1, 2)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000535
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000536 def test_textio_properties(self):
537 memio = self.ioclass()
538
539 # These are just dummy values but we nevertheless check them for fear
540 # of unexpected breakage.
Benjamin Peterson0926ad12009-06-06 18:02:12 +0000541 self.assertIsNone(memio.encoding)
542 self.assertIsNone(memio.errors)
543 self.assertFalse(memio.line_buffering)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000544
Serhiy Storchaka1812bd42014-02-05 13:42:01 +0200545 def test_newline_default(self):
546 memio = self.ioclass("a\nb\r\nc\rd")
547 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
548 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
549
550 memio = self.ioclass()
551 self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
552 memio.seek(0)
553 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
554 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
555
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000556 def test_newline_none(self):
557 # newline=None
558 memio = self.ioclass("a\nb\r\nc\rd", newline=None)
559 self.assertEqual(list(memio), ["a\n", "b\n", "c\n", "d"])
560 memio.seek(0)
561 self.assertEqual(memio.read(1), "a")
562 self.assertEqual(memio.read(2), "\nb")
563 self.assertEqual(memio.read(2), "\nc")
564 self.assertEqual(memio.read(1), "\n")
Serhiy Storchaka1812bd42014-02-05 13:42:01 +0200565 self.assertEqual(memio.getvalue(), "a\nb\nc\nd")
566
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000567 memio = self.ioclass(newline=None)
568 self.assertEqual(2, memio.write("a\n"))
569 self.assertEqual(3, memio.write("b\r\n"))
570 self.assertEqual(3, memio.write("c\rd"))
571 memio.seek(0)
572 self.assertEqual(memio.read(), "a\nb\nc\nd")
Antoine Pitrou57839a62014-02-02 23:37:29 +0100573 self.assertEqual(memio.getvalue(), "a\nb\nc\nd")
Serhiy Storchaka1812bd42014-02-05 13:42:01 +0200574
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000575 memio = self.ioclass("a\r\nb", newline=None)
576 self.assertEqual(memio.read(3), "a\nb")
577
578 def test_newline_empty(self):
579 # newline=""
580 memio = self.ioclass("a\nb\r\nc\rd", newline="")
581 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
582 memio.seek(0)
583 self.assertEqual(memio.read(4), "a\nb\r")
584 self.assertEqual(memio.read(2), "\nc")
585 self.assertEqual(memio.read(1), "\r")
Antoine Pitrou57839a62014-02-02 23:37:29 +0100586 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
Serhiy Storchaka1812bd42014-02-05 13:42:01 +0200587
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000588 memio = self.ioclass(newline="")
589 self.assertEqual(2, memio.write("a\n"))
590 self.assertEqual(2, memio.write("b\r"))
591 self.assertEqual(2, memio.write("\nc"))
592 self.assertEqual(2, memio.write("\rd"))
593 memio.seek(0)
594 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
Serhiy Storchaka1812bd42014-02-05 13:42:01 +0200595 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000596
597 def test_newline_lf(self):
598 # newline="\n"
Serhiy Storchaka1812bd42014-02-05 13:42:01 +0200599 memio = self.ioclass("a\nb\r\nc\rd", newline="\n")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000600 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
Serhiy Storchaka1812bd42014-02-05 13:42:01 +0200601 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
602
603 memio = self.ioclass(newline="\n")
604 self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
605 memio.seek(0)
606 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
607 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000608
609 def test_newline_cr(self):
610 # newline="\r"
611 memio = self.ioclass("a\nb\r\nc\rd", newline="\r")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000612 self.assertEqual(memio.read(), "a\rb\r\rc\rd")
613 memio.seek(0)
614 self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
Serhiy Storchaka1812bd42014-02-05 13:42:01 +0200615 self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd")
616
617 memio = self.ioclass(newline="\r")
618 self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
619 memio.seek(0)
620 self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
Antoine Pitrou57839a62014-02-02 23:37:29 +0100621 memio.seek(0)
622 self.assertEqual(memio.readlines(), ["a\r", "b\r", "\r", "c\r", "d"])
623 self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000624
625 def test_newline_crlf(self):
626 # newline="\r\n"
627 memio = self.ioclass("a\nb\r\nc\rd", newline="\r\n")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000628 self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd")
629 memio.seek(0)
630 self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
Antoine Pitrou57839a62014-02-02 23:37:29 +0100631 memio.seek(0)
632 self.assertEqual(memio.readlines(), ["a\r\n", "b\r\r\n", "c\rd"])
633 self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000634
Serhiy Storchaka1812bd42014-02-05 13:42:01 +0200635 memio = self.ioclass(newline="\r\n")
636 self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
637 memio.seek(0)
638 self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
639 self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd")
640
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000641 def test_issue5265(self):
642 # StringIO can duplicate newlines in universal newlines mode
643 memio = self.ioclass("a\r\nb\r\n", newline=None)
644 self.assertEqual(memio.read(5), "a\nb\n")
Antoine Pitrou57839a62014-02-02 23:37:29 +0100645 self.assertEqual(memio.getvalue(), "a\nb\n")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000646
Alexandre Vassalottid2bb18b2009-07-22 03:07:33 +0000647 def test_newline_argument(self):
648 self.assertRaises(TypeError, self.ioclass, newline=b"\n")
649 self.assertRaises(ValueError, self.ioclass, newline="error")
650 # These should not raise an error
651 for newline in (None, "", "\n", "\r", "\r\n"):
652 self.ioclass(newline=newline)
653
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000654
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000655class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin,
656 TextIOTestMixin, unittest.TestCase):
657 buftype = str
658 ioclass = pyio.StringIO
659 UnsupportedOperation = pyio.UnsupportedOperation
660 EOF = ""
661
Serhiy Storchakac92ea762014-01-29 11:33:26 +0200662 def test_lone_surrogates(self):
663 # Issue #20424
664 memio = self.ioclass('\ud800')
665 self.assertEqual(memio.read(), '\ud800')
666
667 memio = self.ioclass()
668 memio.write('\ud800')
669 self.assertEqual(memio.getvalue(), '\ud800')
670
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000671
672class PyStringIOPickleTest(TextIOTestMixin, unittest.TestCase):
673 """Test if pickle restores properly the internal state of StringIO.
674 """
675 buftype = str
676 UnsupportedOperation = pyio.UnsupportedOperation
677 EOF = ""
678
679 class ioclass(pyio.StringIO):
680 def __new__(cls, *args, **kwargs):
681 return pickle.loads(pickle.dumps(pyio.StringIO(*args, **kwargs)))
682 def __init__(self, *args, **kwargs):
683 pass
684
685
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000686class CBytesIOTest(PyBytesIOTest):
687 ioclass = io.BytesIO
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000688 UnsupportedOperation = io.UnsupportedOperation
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000689
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000690 def test_getstate(self):
691 memio = self.ioclass()
692 state = memio.__getstate__()
693 self.assertEqual(len(state), 3)
694 bytearray(state[0]) # Check if state[0] supports the buffer interface.
Ezio Melottie9615932010-01-24 19:26:24 +0000695 self.assertIsInstance(state[1], int)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000696 self.assertTrue(isinstance(state[2], dict) or state[2] is None)
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000697 memio.close()
698 self.assertRaises(ValueError, memio.__getstate__)
699
700 def test_setstate(self):
701 # This checks whether __setstate__ does proper input validation.
702 memio = self.ioclass()
703 memio.__setstate__((b"no error", 0, None))
704 memio.__setstate__((bytearray(b"no error"), 0, None))
705 memio.__setstate__((b"no error", 0, {'spam': 3}))
706 self.assertRaises(ValueError, memio.__setstate__, (b"", -1, None))
707 self.assertRaises(TypeError, memio.__setstate__, ("unicode", 0, None))
708 self.assertRaises(TypeError, memio.__setstate__, (b"", 0.0, None))
709 self.assertRaises(TypeError, memio.__setstate__, (b"", 0, 0))
710 self.assertRaises(TypeError, memio.__setstate__, (b"len-test", 0))
711 self.assertRaises(TypeError, memio.__setstate__)
712 self.assertRaises(TypeError, memio.__setstate__, 0)
713 memio.close()
714 self.assertRaises(ValueError, memio.__setstate__, (b"closed", 0, None))
715
Antoine Pitrou8f328d02012-07-30 00:01:06 +0200716 check_sizeof = support.check_sizeof
717
718 @support.cpython_only
719 def test_sizeof(self):
Antoine Pitrou754d5ef2012-07-30 13:58:42 +0200720 basesize = support.calcobjsize('P2nN2Pn')
Antoine Pitrou8f328d02012-07-30 00:01:06 +0200721 check = self.check_sizeof
722 self.assertEqual(object.__sizeof__(io.BytesIO()), basesize)
723 check(io.BytesIO(), basesize )
724 check(io.BytesIO(b'a'), basesize + 1 + 1 )
725 check(io.BytesIO(b'a' * 1000), basesize + 1000 + 1 )
726
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000727class CStringIOTest(PyStringIOTest):
728 ioclass = io.StringIO
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000729 UnsupportedOperation = io.UnsupportedOperation
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000730
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000731 # XXX: For the Python version of io.StringIO, this is highly
732 # dependent on the encoding used for the underlying buffer.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000733 def test_widechar(self):
734 buf = self.buftype("\U0002030a\U00020347")
735 memio = self.ioclass(buf)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000736
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000737 self.assertEqual(memio.getvalue(), buf)
738 self.assertEqual(memio.write(buf), len(buf))
739 self.assertEqual(memio.tell(), len(buf))
740 self.assertEqual(memio.getvalue(), buf)
741 self.assertEqual(memio.write(buf), len(buf))
742 self.assertEqual(memio.tell(), len(buf) * 2)
743 self.assertEqual(memio.getvalue(), buf + buf)
Alexandre Vassalotti794652d2008-06-11 22:58:36 +0000744
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000745 def test_getstate(self):
746 memio = self.ioclass()
747 state = memio.__getstate__()
748 self.assertEqual(len(state), 4)
Ezio Melottie9615932010-01-24 19:26:24 +0000749 self.assertIsInstance(state[0], str)
750 self.assertIsInstance(state[1], str)
751 self.assertIsInstance(state[2], int)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000752 self.assertTrue(isinstance(state[3], dict) or state[3] is None)
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000753 memio.close()
754 self.assertRaises(ValueError, memio.__getstate__)
755
756 def test_setstate(self):
757 # This checks whether __setstate__ does proper input validation.
758 memio = self.ioclass()
759 memio.__setstate__(("no error", "\n", 0, None))
760 memio.__setstate__(("no error", "", 0, {'spam': 3}))
761 self.assertRaises(ValueError, memio.__setstate__, ("", "f", 0, None))
762 self.assertRaises(ValueError, memio.__setstate__, ("", "", -1, None))
763 self.assertRaises(TypeError, memio.__setstate__, (b"", "", 0, None))
764 self.assertRaises(TypeError, memio.__setstate__, ("", b"", 0, None))
765 self.assertRaises(TypeError, memio.__setstate__, ("", "", 0.0, None))
766 self.assertRaises(TypeError, memio.__setstate__, ("", "", 0, 0))
767 self.assertRaises(TypeError, memio.__setstate__, ("len-test", 0))
768 self.assertRaises(TypeError, memio.__setstate__)
769 self.assertRaises(TypeError, memio.__setstate__, 0)
770 memio.close()
771 self.assertRaises(ValueError, memio.__setstate__, ("closed", "", 0, None))
772
773
774class CStringIOPickleTest(PyStringIOPickleTest):
775 UnsupportedOperation = io.UnsupportedOperation
776
777 class ioclass(io.StringIO):
778 def __new__(cls, *args, **kwargs):
779 return pickle.loads(pickle.dumps(io.StringIO(*args, **kwargs)))
780 def __init__(self, *args, **kwargs):
781 pass
782
Alexandre Vassalotti794652d2008-06-11 22:58:36 +0000783
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000784def test_main():
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000785 tests = [PyBytesIOTest, PyStringIOTest, CBytesIOTest, CStringIOTest,
786 PyStringIOPickleTest, CStringIOPickleTest]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000787 support.run_unittest(*tests)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000788
789if __name__ == '__main__':
790 test_main()