blob: b3fc0422d7bd07866dd367b535943a5b81c0900b [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 Vassalotti1bfe9dc82008-05-07 01:44:31 +000011import sys
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
23 self.assertEquals(buf[:1], bytesIo.read(1))
24 self.assertEquals(buf[1:5], bytesIo.read(4))
25 self.assertEquals(buf[5:], bytesIo.read(900))
26 self.assertEquals(self.EOF, bytesIo.read())
27
28 def testReadNoArgs(self):
29 buf = self.buftype("1234567890")
30 bytesIo = self.ioclass(buf)
31
32 self.assertEquals(buf, bytesIo.read())
33 self.assertEquals(self.EOF, bytesIo.read())
34
35 def testSeek(self):
36 buf = self.buftype("1234567890")
37 bytesIo = self.ioclass(buf)
38
39 bytesIo.read(5)
40 bytesIo.seek(0)
41 self.assertEquals(buf, bytesIo.read())
42
43 bytesIo.seek(3)
44 self.assertEquals(buf[3:], bytesIo.read())
45 self.assertRaises(TypeError, bytesIo.seek, 0.0)
46
47 def testTell(self):
48 buf = self.buftype("1234567890")
49 bytesIo = self.ioclass(buf)
50
51 self.assertEquals(0, bytesIo.tell())
52 bytesIo.seek(5)
53 self.assertEquals(5, bytesIo.tell())
54 bytesIo.seek(10000)
55 self.assertEquals(10000, bytesIo.tell())
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000056
57
58class MemoryTestMixin:
59
60 def write_ops(self, f, t):
61 self.assertEqual(f.write(t("blah.")), 5)
62 self.assertEqual(f.seek(0), 0)
63 self.assertEqual(f.write(t("Hello.")), 6)
64 self.assertEqual(f.tell(), 6)
65 self.assertEqual(f.seek(5), 5)
66 self.assertEqual(f.tell(), 5)
67 self.assertEqual(f.write(t(" world\n\n\n")), 9)
68 self.assertEqual(f.seek(0), 0)
69 self.assertEqual(f.write(t("h")), 1)
70 self.assertEqual(f.truncate(12), 12)
71 self.assertEqual(f.tell(), 12)
72
73 def test_write(self):
74 buf = self.buftype("hello world\n")
75 memio = self.ioclass(buf)
76
77 self.write_ops(memio, self.buftype)
78 self.assertEqual(memio.getvalue(), buf)
79 memio = self.ioclass()
80 self.write_ops(memio, self.buftype)
81 self.assertEqual(memio.getvalue(), buf)
82 self.assertRaises(TypeError, memio.write, None)
83 memio.close()
84 self.assertRaises(ValueError, memio.write, self.buftype(""))
85
86 def test_writelines(self):
87 buf = self.buftype("1234567890")
88 memio = self.ioclass()
89
90 self.assertEqual(memio.writelines([buf] * 100), None)
91 self.assertEqual(memio.getvalue(), buf * 100)
92 memio.writelines([])
93 self.assertEqual(memio.getvalue(), buf * 100)
94 memio = self.ioclass()
95 self.assertRaises(TypeError, memio.writelines, [buf] + [1])
96 self.assertEqual(memio.getvalue(), buf)
97 self.assertRaises(TypeError, memio.writelines, None)
98 memio.close()
99 self.assertRaises(ValueError, memio.writelines, [])
100
101 def test_writelines_error(self):
102 memio = self.ioclass()
103 def error_gen():
104 yield self.buftype('spam')
105 raise KeyboardInterrupt
106
107 self.assertRaises(KeyboardInterrupt, memio.writelines, error_gen())
108
109 def test_truncate(self):
110 buf = self.buftype("1234567890")
111 memio = self.ioclass(buf)
112
113 self.assertRaises(ValueError, memio.truncate, -1)
114 memio.seek(6)
115 self.assertEqual(memio.truncate(), 6)
116 self.assertEqual(memio.getvalue(), buf[:6])
117 self.assertEqual(memio.truncate(4), 4)
118 self.assertEqual(memio.getvalue(), buf[:4])
119 self.assertEqual(memio.tell(), 4)
120 memio.write(buf)
121 self.assertEqual(memio.getvalue(), buf[:4] + buf)
122 pos = memio.tell()
123 self.assertEqual(memio.truncate(None), pos)
124 self.assertEqual(memio.tell(), pos)
125 self.assertRaises(TypeError, memio.truncate, '0')
126 memio.close()
127 self.assertRaises(ValueError, memio.truncate, 0)
128
129 def test_init(self):
130 buf = self.buftype("1234567890")
131 memio = self.ioclass(buf)
132 self.assertEqual(memio.getvalue(), buf)
133 memio = self.ioclass(None)
134 self.assertEqual(memio.getvalue(), self.EOF)
135 memio.__init__(buf * 2)
136 self.assertEqual(memio.getvalue(), buf * 2)
137 memio.__init__(buf)
138 self.assertEqual(memio.getvalue(), buf)
139
140 def test_read(self):
141 buf = self.buftype("1234567890")
142 memio = self.ioclass(buf)
143
144 self.assertEqual(memio.read(0), self.EOF)
145 self.assertEqual(memio.read(1), buf[:1])
146 self.assertEqual(memio.read(4), buf[1:5])
147 self.assertEqual(memio.read(900), buf[5:])
148 self.assertEqual(memio.read(), self.EOF)
149 memio.seek(0)
150 self.assertEqual(memio.read(), buf)
151 self.assertEqual(memio.read(), self.EOF)
152 self.assertEqual(memio.tell(), 10)
153 memio.seek(0)
154 self.assertEqual(memio.read(-1), buf)
155 memio.seek(0)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000156 self.assertEqual(type(memio.read()), type(buf))
Alexandre Vassalotti4833b3c2008-05-06 23:47:23 +0000157 memio.seek(100)
158 self.assertEqual(type(memio.read()), type(buf))
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000159 memio.seek(0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000160 self.assertEqual(memio.read(None), buf)
161 self.assertRaises(TypeError, memio.read, '')
162 memio.close()
163 self.assertRaises(ValueError, memio.read)
164
165 def test_readline(self):
166 buf = self.buftype("1234567890\n")
167 memio = self.ioclass(buf * 2)
168
169 self.assertEqual(memio.readline(0), self.EOF)
170 self.assertEqual(memio.readline(), buf)
171 self.assertEqual(memio.readline(), buf)
172 self.assertEqual(memio.readline(), self.EOF)
173 memio.seek(0)
174 self.assertEqual(memio.readline(5), buf[:5])
175 self.assertEqual(memio.readline(5), buf[5:10])
176 self.assertEqual(memio.readline(5), buf[10:15])
177 memio.seek(0)
178 self.assertEqual(memio.readline(-1), buf)
179 memio.seek(0)
180 self.assertEqual(memio.readline(0), self.EOF)
181
182 buf = self.buftype("1234567890\n")
183 memio = self.ioclass((buf * 3)[:-1])
184 self.assertEqual(memio.readline(), buf)
185 self.assertEqual(memio.readline(), buf)
186 self.assertEqual(memio.readline(), buf[:-1])
187 self.assertEqual(memio.readline(), self.EOF)
188 memio.seek(0)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000189 self.assertEqual(type(memio.readline()), type(buf))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000190 self.assertEqual(memio.readline(), buf)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000191 self.assertRaises(TypeError, memio.readline, '')
192 memio.close()
193 self.assertRaises(ValueError, memio.readline)
194
195 def test_readlines(self):
196 buf = self.buftype("1234567890\n")
197 memio = self.ioclass(buf * 10)
198
199 self.assertEqual(memio.readlines(), [buf] * 10)
200 memio.seek(5)
201 self.assertEqual(memio.readlines(), [buf[5:]] + [buf] * 9)
202 memio.seek(0)
203 self.assertEqual(memio.readlines(15), [buf] * 2)
204 memio.seek(0)
205 self.assertEqual(memio.readlines(-1), [buf] * 10)
206 memio.seek(0)
207 self.assertEqual(memio.readlines(0), [buf] * 10)
208 memio.seek(0)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000209 self.assertEqual(type(memio.readlines()[0]), type(buf))
210 memio.seek(0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000211 self.assertEqual(memio.readlines(None), [buf] * 10)
212 self.assertRaises(TypeError, memio.readlines, '')
213 memio.close()
214 self.assertRaises(ValueError, memio.readlines)
215
216 def test_iterator(self):
217 buf = self.buftype("1234567890\n")
218 memio = self.ioclass(buf * 10)
219
220 self.assertEqual(iter(memio), memio)
221 self.failUnless(hasattr(memio, '__iter__'))
222 self.failUnless(hasattr(memio, '__next__'))
223 i = 0
224 for line in memio:
225 self.assertEqual(line, buf)
226 i += 1
227 self.assertEqual(i, 10)
228 memio.seek(0)
229 i = 0
230 for line in memio:
231 self.assertEqual(line, buf)
232 i += 1
233 self.assertEqual(i, 10)
234 memio = self.ioclass(buf * 2)
235 memio.close()
236 self.assertRaises(ValueError, memio.__next__)
237
238 def test_getvalue(self):
239 buf = self.buftype("1234567890")
240 memio = self.ioclass(buf)
241
242 self.assertEqual(memio.getvalue(), buf)
243 memio.read()
244 self.assertEqual(memio.getvalue(), buf)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000245 self.assertEqual(type(memio.getvalue()), type(buf))
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000246 memio = self.ioclass(buf * 1000)
247 self.assertEqual(memio.getvalue()[-3:], self.buftype("890"))
248 memio = self.ioclass(buf)
249 memio.close()
250 self.assertRaises(ValueError, memio.getvalue)
251
252 def test_seek(self):
253 buf = self.buftype("1234567890")
254 memio = self.ioclass(buf)
255
256 memio.read(5)
257 self.assertRaises(ValueError, memio.seek, -1)
258 self.assertRaises(ValueError, memio.seek, 1, -1)
259 self.assertRaises(ValueError, memio.seek, 1, 3)
260 self.assertEqual(memio.seek(0), 0)
261 self.assertEqual(memio.seek(0, 0), 0)
262 self.assertEqual(memio.read(), buf)
263 self.assertEqual(memio.seek(3), 3)
264 self.assertEqual(memio.seek(0, 1), 3)
265 self.assertEqual(memio.read(), buf[3:])
266 self.assertEqual(memio.seek(len(buf)), len(buf))
267 self.assertEqual(memio.read(), self.EOF)
268 memio.seek(len(buf) + 1)
269 self.assertEqual(memio.read(), self.EOF)
270 self.assertEqual(memio.seek(0, 2), len(buf))
271 self.assertEqual(memio.read(), self.EOF)
272 memio.close()
273 self.assertRaises(ValueError, memio.seek, 0)
274
275 def test_overseek(self):
276 buf = self.buftype("1234567890")
277 memio = self.ioclass(buf)
278
279 self.assertEqual(memio.seek(len(buf) + 1), 11)
280 self.assertEqual(memio.read(), self.EOF)
281 self.assertEqual(memio.tell(), 11)
282 self.assertEqual(memio.getvalue(), buf)
283 memio.write(self.EOF)
284 self.assertEqual(memio.getvalue(), buf)
285 memio.write(buf)
286 self.assertEqual(memio.getvalue(), buf + self.buftype('\0') + buf)
287
288 def test_tell(self):
289 buf = self.buftype("1234567890")
290 memio = self.ioclass(buf)
291
292 self.assertEqual(memio.tell(), 0)
293 memio.seek(5)
294 self.assertEqual(memio.tell(), 5)
295 memio.seek(10000)
296 self.assertEqual(memio.tell(), 10000)
297 memio.close()
298 self.assertRaises(ValueError, memio.tell)
299
300 def test_flush(self):
301 buf = self.buftype("1234567890")
302 memio = self.ioclass(buf)
303
304 self.assertEqual(memio.flush(), None)
305
306 def test_flags(self):
307 memio = self.ioclass()
308
309 self.assertEqual(memio.writable(), True)
310 self.assertEqual(memio.readable(), True)
311 self.assertEqual(memio.seekable(), True)
312 self.assertEqual(memio.isatty(), False)
313 self.assertEqual(memio.closed, False)
314 memio.close()
315 self.assertEqual(memio.writable(), True)
316 self.assertEqual(memio.readable(), True)
317 self.assertEqual(memio.seekable(), True)
318 self.assertRaises(ValueError, memio.isatty)
319 self.assertEqual(memio.closed, True)
320
321 def test_subclassing(self):
322 buf = self.buftype("1234567890")
323 def test1():
324 class MemIO(self.ioclass):
325 pass
326 m = MemIO(buf)
327 return m.getvalue()
328 def test2():
329 class MemIO(self.ioclass):
330 def __init__(me, a, b):
331 self.ioclass.__init__(me, a)
332 m = MemIO(buf, None)
333 return m.getvalue()
334 self.assertEqual(test1(), buf)
335 self.assertEqual(test2(), buf)
336
337
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000338class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000339 @staticmethod
340 def buftype(s):
341 return s.encode("ascii")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000342 ioclass = pyio.BytesIO
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000343 EOF = b""
344
345 def test_read1(self):
346 buf = self.buftype("1234567890")
347 memio = self.ioclass(buf)
348
349 self.assertRaises(TypeError, memio.read1)
350 self.assertEqual(memio.read(), buf)
351
352 def test_readinto(self):
353 buf = self.buftype("1234567890")
354 memio = self.ioclass(buf)
355
356 b = bytearray(b"hello")
357 self.assertEqual(memio.readinto(b), 5)
358 self.assertEqual(b, b"12345")
359 self.assertEqual(memio.readinto(b), 5)
360 self.assertEqual(b, b"67890")
361 self.assertEqual(memio.readinto(b), 0)
362 self.assertEqual(b, b"67890")
363 b = bytearray(b"hello world")
364 memio.seek(0)
365 self.assertEqual(memio.readinto(b), 10)
366 self.assertEqual(b, b"1234567890d")
367 b = bytearray(b"")
368 memio.seek(0)
369 self.assertEqual(memio.readinto(b), 0)
370 self.assertEqual(b, b"")
371 self.assertRaises(TypeError, memio.readinto, '')
372 import array
373 a = array.array('b', b"hello world")
374 memio = self.ioclass(buf)
375 memio.readinto(a)
376 self.assertEqual(a.tostring(), b"1234567890d")
377 memio.close()
378 self.assertRaises(ValueError, memio.readinto, b)
379
380 def test_relative_seek(self):
381 buf = self.buftype("1234567890")
382 memio = self.ioclass(buf)
383
384 self.assertEqual(memio.seek(-1, 1), 0)
385 self.assertEqual(memio.seek(3, 1), 3)
386 self.assertEqual(memio.seek(-4, 1), 0)
387 self.assertEqual(memio.seek(-1, 2), 9)
388 self.assertEqual(memio.seek(1, 1), 10)
389 self.assertEqual(memio.seek(1, 2), 11)
390 memio.seek(-3, 2)
391 self.assertEqual(memio.read(), buf[-3:])
392 memio.seek(0)
393 memio.seek(1, 1)
394 self.assertEqual(memio.read(), buf[1:])
395
396 def test_unicode(self):
397 memio = self.ioclass()
398
399 self.assertRaises(TypeError, self.ioclass, "1234567890")
400 self.assertRaises(TypeError, memio.write, "1234567890")
401 self.assertRaises(TypeError, memio.writelines, ["1234567890"])
402
403 def test_bytes_array(self):
404 buf = b"1234567890"
405 import array
406 a = array.array('b', list(buf))
407 memio = self.ioclass(a)
408 self.assertEqual(memio.getvalue(), buf)
409 self.assertEqual(memio.write(a), 10)
410 self.assertEqual(memio.getvalue(), buf)
411
412
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000413class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000414 buftype = str
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000415 ioclass = pyio.StringIO
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000416 EOF = ""
417
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000418 # TextIO-specific behaviour.
419
420 def test_newlines_property(self):
421 memio = self.ioclass(newline=None)
422 # The C StringIO decodes newlines in write() calls, but the Python
423 # implementation only does when reading. This function forces them to
424 # be decoded for testing.
425 def force_decode():
426 memio.seek(0)
427 memio.read()
428 self.assertEqual(memio.newlines, None)
429 memio.write("a\n")
430 force_decode()
431 self.assertEqual(memio.newlines, "\n")
432 memio.write("b\r\n")
433 force_decode()
434 self.assertEqual(memio.newlines, ("\n", "\r\n"))
435 memio.write("c\rd")
436 force_decode()
437 self.assertEqual(memio.newlines, ("\r", "\n", "\r\n"))
438
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000439 def test_relative_seek(self):
440 memio = self.ioclass()
441
442 self.assertRaises(IOError, memio.seek, -1, 1)
443 self.assertRaises(IOError, memio.seek, 3, 1)
444 self.assertRaises(IOError, memio.seek, -3, 1)
445 self.assertRaises(IOError, memio.seek, -1, 2)
446 self.assertRaises(IOError, memio.seek, 1, 1)
447 self.assertRaises(IOError, memio.seek, 1, 2)
448
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000449 def test_textio_properties(self):
450 memio = self.ioclass()
451
452 # These are just dummy values but we nevertheless check them for fear
453 # of unexpected breakage.
454 self.assertEqual(memio.encoding, "utf-8")
455 self.assertEqual(memio.errors, "strict")
456 self.assertEqual(memio.line_buffering, False)
457
458 def test_newline_none(self):
459 # newline=None
460 memio = self.ioclass("a\nb\r\nc\rd", newline=None)
461 self.assertEqual(list(memio), ["a\n", "b\n", "c\n", "d"])
462 memio.seek(0)
463 self.assertEqual(memio.read(1), "a")
464 self.assertEqual(memio.read(2), "\nb")
465 self.assertEqual(memio.read(2), "\nc")
466 self.assertEqual(memio.read(1), "\n")
467 memio = self.ioclass(newline=None)
468 self.assertEqual(2, memio.write("a\n"))
469 self.assertEqual(3, memio.write("b\r\n"))
470 self.assertEqual(3, memio.write("c\rd"))
471 memio.seek(0)
472 self.assertEqual(memio.read(), "a\nb\nc\nd")
473 memio = self.ioclass("a\r\nb", newline=None)
474 self.assertEqual(memio.read(3), "a\nb")
475
476 def test_newline_empty(self):
477 # newline=""
478 memio = self.ioclass("a\nb\r\nc\rd", newline="")
479 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
480 memio.seek(0)
481 self.assertEqual(memio.read(4), "a\nb\r")
482 self.assertEqual(memio.read(2), "\nc")
483 self.assertEqual(memio.read(1), "\r")
484 memio = self.ioclass(newline="")
485 self.assertEqual(2, memio.write("a\n"))
486 self.assertEqual(2, memio.write("b\r"))
487 self.assertEqual(2, memio.write("\nc"))
488 self.assertEqual(2, memio.write("\rd"))
489 memio.seek(0)
490 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
491
492 def test_newline_lf(self):
493 # newline="\n"
494 memio = self.ioclass("a\nb\r\nc\rd")
495 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
496
497 def test_newline_cr(self):
498 # newline="\r"
499 memio = self.ioclass("a\nb\r\nc\rd", newline="\r")
500 memio.seek(0)
501 self.assertEqual(memio.read(), "a\rb\r\rc\rd")
502 memio.seek(0)
503 self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
504
505 def test_newline_crlf(self):
506 # newline="\r\n"
507 memio = self.ioclass("a\nb\r\nc\rd", newline="\r\n")
508 memio.seek(0)
509 self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd")
510 memio.seek(0)
511 self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
512
513 def test_issue5265(self):
514 # StringIO can duplicate newlines in universal newlines mode
515 memio = self.ioclass("a\r\nb\r\n", newline=None)
516 self.assertEqual(memio.read(5), "a\nb\n")
517
518
519class CBytesIOTest(PyBytesIOTest):
520 ioclass = io.BytesIO
521
522class CStringIOTest(PyStringIOTest):
523 ioclass = io.StringIO
524
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000525 # XXX: For the Python version of io.StringIO, this is highly
526 # dependent on the encoding used for the underlying buffer.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000527 def test_widechar(self):
528 buf = self.buftype("\U0002030a\U00020347")
529 memio = self.ioclass(buf)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000530
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000531 self.assertEqual(memio.getvalue(), buf)
532 self.assertEqual(memio.write(buf), len(buf))
533 self.assertEqual(memio.tell(), len(buf))
534 self.assertEqual(memio.getvalue(), buf)
535 self.assertEqual(memio.write(buf), len(buf))
536 self.assertEqual(memio.tell(), len(buf) * 2)
537 self.assertEqual(memio.getvalue(), buf + buf)
Alexandre Vassalotti794652d2008-06-11 22:58:36 +0000538
539
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000540def test_main():
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000541 tests = [PyBytesIOTest, PyStringIOTest, CBytesIOTest, CStringIOTest]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000542 support.run_unittest(*tests)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000543
544if __name__ == '__main__':
545 test_main()