make file closing more robust
[python/dscho.git] / Lib / test / test_memoryio.py
blob0d044e96ba1523bc1ced69690308bba89f71416b
1 """Unit tests for memory-based file-like objects.
2 StringIO -- for unicode strings
3 BytesIO -- for bytes
4 """
6 import unittest
7 from test import support
9 import io
10 import _pyio as pyio
11 import sys
13 class MemorySeekTestMixin:
15 def testInit(self):
16 buf = self.buftype("1234567890")
17 bytesIo = self.ioclass(buf)
19 def testRead(self):
20 buf = self.buftype("1234567890")
21 bytesIo = self.ioclass(buf)
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())
28 def testReadNoArgs(self):
29 buf = self.buftype("1234567890")
30 bytesIo = self.ioclass(buf)
32 self.assertEquals(buf, bytesIo.read())
33 self.assertEquals(self.EOF, bytesIo.read())
35 def testSeek(self):
36 buf = self.buftype("1234567890")
37 bytesIo = self.ioclass(buf)
39 bytesIo.read(5)
40 bytesIo.seek(0)
41 self.assertEquals(buf, bytesIo.read())
43 bytesIo.seek(3)
44 self.assertEquals(buf[3:], bytesIo.read())
45 self.assertRaises(TypeError, bytesIo.seek, 0.0)
47 def testTell(self):
48 buf = self.buftype("1234567890")
49 bytesIo = self.ioclass(buf)
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())
58 class MemoryTestMixin:
60 def test_detach(self):
61 buf = self.ioclass()
62 self.assertRaises(self.UnsupportedOperation, buf.detach)
64 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)
75 self.assertEqual(f.tell(), 12)
77 def test_write(self):
78 buf = self.buftype("hello world\n")
79 memio = self.ioclass(buf)
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(""))
90 def test_writelines(self):
91 buf = self.buftype("1234567890")
92 memio = self.ioclass()
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, [])
105 def test_writelines_error(self):
106 memio = self.ioclass()
107 def error_gen():
108 yield self.buftype('spam')
109 raise KeyboardInterrupt
111 self.assertRaises(KeyboardInterrupt, memio.writelines, error_gen())
113 def test_truncate(self):
114 buf = self.buftype("1234567890")
115 memio = self.ioclass(buf)
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])
123 self.assertEqual(memio.tell(), 4)
124 memio.write(buf)
125 self.assertEqual(memio.getvalue(), buf[:4] + buf)
126 pos = memio.tell()
127 self.assertEqual(memio.truncate(None), pos)
128 self.assertEqual(memio.tell(), pos)
129 self.assertRaises(TypeError, memio.truncate, '0')
130 memio.close()
131 self.assertRaises(ValueError, memio.truncate, 0)
133 def test_init(self):
134 buf = self.buftype("1234567890")
135 memio = self.ioclass(buf)
136 self.assertEqual(memio.getvalue(), buf)
137 memio = self.ioclass(None)
138 self.assertEqual(memio.getvalue(), self.EOF)
139 memio.__init__(buf * 2)
140 self.assertEqual(memio.getvalue(), buf * 2)
141 memio.__init__(buf)
142 self.assertEqual(memio.getvalue(), buf)
144 def test_read(self):
145 buf = self.buftype("1234567890")
146 memio = self.ioclass(buf)
148 self.assertEqual(memio.read(0), self.EOF)
149 self.assertEqual(memio.read(1), buf[:1])
150 self.assertEqual(memio.read(4), buf[1:5])
151 self.assertEqual(memio.read(900), buf[5:])
152 self.assertEqual(memio.read(), self.EOF)
153 memio.seek(0)
154 self.assertEqual(memio.read(), buf)
155 self.assertEqual(memio.read(), self.EOF)
156 self.assertEqual(memio.tell(), 10)
157 memio.seek(0)
158 self.assertEqual(memio.read(-1), buf)
159 memio.seek(0)
160 self.assertEqual(type(memio.read()), type(buf))
161 memio.seek(100)
162 self.assertEqual(type(memio.read()), type(buf))
163 memio.seek(0)
164 self.assertEqual(memio.read(None), buf)
165 self.assertRaises(TypeError, memio.read, '')
166 memio.close()
167 self.assertRaises(ValueError, memio.read)
169 def test_readline(self):
170 buf = self.buftype("1234567890\n")
171 memio = self.ioclass(buf * 2)
173 self.assertEqual(memio.readline(0), self.EOF)
174 self.assertEqual(memio.readline(), buf)
175 self.assertEqual(memio.readline(), buf)
176 self.assertEqual(memio.readline(), self.EOF)
177 memio.seek(0)
178 self.assertEqual(memio.readline(5), buf[:5])
179 self.assertEqual(memio.readline(5), buf[5:10])
180 self.assertEqual(memio.readline(5), buf[10:15])
181 memio.seek(0)
182 self.assertEqual(memio.readline(-1), buf)
183 memio.seek(0)
184 self.assertEqual(memio.readline(0), self.EOF)
186 buf = self.buftype("1234567890\n")
187 memio = self.ioclass((buf * 3)[:-1])
188 self.assertEqual(memio.readline(), buf)
189 self.assertEqual(memio.readline(), buf)
190 self.assertEqual(memio.readline(), buf[:-1])
191 self.assertEqual(memio.readline(), self.EOF)
192 memio.seek(0)
193 self.assertEqual(type(memio.readline()), type(buf))
194 self.assertEqual(memio.readline(), buf)
195 self.assertRaises(TypeError, memio.readline, '')
196 memio.close()
197 self.assertRaises(ValueError, memio.readline)
199 def test_readlines(self):
200 buf = self.buftype("1234567890\n")
201 memio = self.ioclass(buf * 10)
203 self.assertEqual(memio.readlines(), [buf] * 10)
204 memio.seek(5)
205 self.assertEqual(memio.readlines(), [buf[5:]] + [buf] * 9)
206 memio.seek(0)
207 self.assertEqual(memio.readlines(15), [buf] * 2)
208 memio.seek(0)
209 self.assertEqual(memio.readlines(-1), [buf] * 10)
210 memio.seek(0)
211 self.assertEqual(memio.readlines(0), [buf] * 10)
212 memio.seek(0)
213 self.assertEqual(type(memio.readlines()[0]), type(buf))
214 memio.seek(0)
215 self.assertEqual(memio.readlines(None), [buf] * 10)
216 self.assertRaises(TypeError, memio.readlines, '')
217 memio.close()
218 self.assertRaises(ValueError, memio.readlines)
220 def test_iterator(self):
221 buf = self.buftype("1234567890\n")
222 memio = self.ioclass(buf * 10)
224 self.assertEqual(iter(memio), memio)
225 self.failUnless(hasattr(memio, '__iter__'))
226 self.failUnless(hasattr(memio, '__next__'))
227 i = 0
228 for line in memio:
229 self.assertEqual(line, buf)
230 i += 1
231 self.assertEqual(i, 10)
232 memio.seek(0)
233 i = 0
234 for line in memio:
235 self.assertEqual(line, buf)
236 i += 1
237 self.assertEqual(i, 10)
238 memio = self.ioclass(buf * 2)
239 memio.close()
240 self.assertRaises(ValueError, memio.__next__)
242 def test_getvalue(self):
243 buf = self.buftype("1234567890")
244 memio = self.ioclass(buf)
246 self.assertEqual(memio.getvalue(), buf)
247 memio.read()
248 self.assertEqual(memio.getvalue(), buf)
249 self.assertEqual(type(memio.getvalue()), type(buf))
250 memio = self.ioclass(buf * 1000)
251 self.assertEqual(memio.getvalue()[-3:], self.buftype("890"))
252 memio = self.ioclass(buf)
253 memio.close()
254 self.assertRaises(ValueError, memio.getvalue)
256 def test_seek(self):
257 buf = self.buftype("1234567890")
258 memio = self.ioclass(buf)
260 memio.read(5)
261 self.assertRaises(ValueError, memio.seek, -1)
262 self.assertRaises(ValueError, memio.seek, 1, -1)
263 self.assertRaises(ValueError, memio.seek, 1, 3)
264 self.assertEqual(memio.seek(0), 0)
265 self.assertEqual(memio.seek(0, 0), 0)
266 self.assertEqual(memio.read(), buf)
267 self.assertEqual(memio.seek(3), 3)
268 self.assertEqual(memio.seek(0, 1), 3)
269 self.assertEqual(memio.read(), buf[3:])
270 self.assertEqual(memio.seek(len(buf)), len(buf))
271 self.assertEqual(memio.read(), self.EOF)
272 memio.seek(len(buf) + 1)
273 self.assertEqual(memio.read(), self.EOF)
274 self.assertEqual(memio.seek(0, 2), len(buf))
275 self.assertEqual(memio.read(), self.EOF)
276 memio.close()
277 self.assertRaises(ValueError, memio.seek, 0)
279 def test_overseek(self):
280 buf = self.buftype("1234567890")
281 memio = self.ioclass(buf)
283 self.assertEqual(memio.seek(len(buf) + 1), 11)
284 self.assertEqual(memio.read(), self.EOF)
285 self.assertEqual(memio.tell(), 11)
286 self.assertEqual(memio.getvalue(), buf)
287 memio.write(self.EOF)
288 self.assertEqual(memio.getvalue(), buf)
289 memio.write(buf)
290 self.assertEqual(memio.getvalue(), buf + self.buftype('\0') + buf)
292 def test_tell(self):
293 buf = self.buftype("1234567890")
294 memio = self.ioclass(buf)
296 self.assertEqual(memio.tell(), 0)
297 memio.seek(5)
298 self.assertEqual(memio.tell(), 5)
299 memio.seek(10000)
300 self.assertEqual(memio.tell(), 10000)
301 memio.close()
302 self.assertRaises(ValueError, memio.tell)
304 def test_flush(self):
305 buf = self.buftype("1234567890")
306 memio = self.ioclass(buf)
308 self.assertEqual(memio.flush(), None)
310 def test_flags(self):
311 memio = self.ioclass()
313 self.assertEqual(memio.writable(), True)
314 self.assertEqual(memio.readable(), True)
315 self.assertEqual(memio.seekable(), True)
316 self.assertEqual(memio.isatty(), False)
317 self.assertEqual(memio.closed, False)
318 memio.close()
319 self.assertEqual(memio.writable(), True)
320 self.assertEqual(memio.readable(), True)
321 self.assertEqual(memio.seekable(), True)
322 self.assertRaises(ValueError, memio.isatty)
323 self.assertEqual(memio.closed, True)
325 def test_subclassing(self):
326 buf = self.buftype("1234567890")
327 def test1():
328 class MemIO(self.ioclass):
329 pass
330 m = MemIO(buf)
331 return m.getvalue()
332 def test2():
333 class MemIO(self.ioclass):
334 def __init__(me, a, b):
335 self.ioclass.__init__(me, a)
336 m = MemIO(buf, None)
337 return m.getvalue()
338 self.assertEqual(test1(), buf)
339 self.assertEqual(test2(), buf)
342 class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
344 UnsupportedOperation = pyio.UnsupportedOperation
346 @staticmethod
347 def buftype(s):
348 return s.encode("ascii")
349 ioclass = pyio.BytesIO
350 EOF = b""
352 def test_read1(self):
353 buf = self.buftype("1234567890")
354 memio = self.ioclass(buf)
356 self.assertRaises(TypeError, memio.read1)
357 self.assertEqual(memio.read(), buf)
359 def test_readinto(self):
360 buf = self.buftype("1234567890")
361 memio = self.ioclass(buf)
363 b = bytearray(b"hello")
364 self.assertEqual(memio.readinto(b), 5)
365 self.assertEqual(b, b"12345")
366 self.assertEqual(memio.readinto(b), 5)
367 self.assertEqual(b, b"67890")
368 self.assertEqual(memio.readinto(b), 0)
369 self.assertEqual(b, b"67890")
370 b = bytearray(b"hello world")
371 memio.seek(0)
372 self.assertEqual(memio.readinto(b), 10)
373 self.assertEqual(b, b"1234567890d")
374 b = bytearray(b"")
375 memio.seek(0)
376 self.assertEqual(memio.readinto(b), 0)
377 self.assertEqual(b, b"")
378 self.assertRaises(TypeError, memio.readinto, '')
379 import array
380 a = array.array('b', b"hello world")
381 memio = self.ioclass(buf)
382 memio.readinto(a)
383 self.assertEqual(a.tostring(), b"1234567890d")
384 memio.close()
385 self.assertRaises(ValueError, memio.readinto, b)
387 def test_relative_seek(self):
388 buf = self.buftype("1234567890")
389 memio = self.ioclass(buf)
391 self.assertEqual(memio.seek(-1, 1), 0)
392 self.assertEqual(memio.seek(3, 1), 3)
393 self.assertEqual(memio.seek(-4, 1), 0)
394 self.assertEqual(memio.seek(-1, 2), 9)
395 self.assertEqual(memio.seek(1, 1), 10)
396 self.assertEqual(memio.seek(1, 2), 11)
397 memio.seek(-3, 2)
398 self.assertEqual(memio.read(), buf[-3:])
399 memio.seek(0)
400 memio.seek(1, 1)
401 self.assertEqual(memio.read(), buf[1:])
403 def test_unicode(self):
404 memio = self.ioclass()
406 self.assertRaises(TypeError, self.ioclass, "1234567890")
407 self.assertRaises(TypeError, memio.write, "1234567890")
408 self.assertRaises(TypeError, memio.writelines, ["1234567890"])
410 def test_bytes_array(self):
411 buf = b"1234567890"
412 import array
413 a = array.array('b', list(buf))
414 memio = self.ioclass(a)
415 self.assertEqual(memio.getvalue(), buf)
416 self.assertEqual(memio.write(a), 10)
417 self.assertEqual(memio.getvalue(), buf)
420 class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
421 buftype = str
422 ioclass = pyio.StringIO
423 UnsupportedOperation = pyio.UnsupportedOperation
424 EOF = ""
426 # TextIO-specific behaviour.
428 def test_newlines_property(self):
429 memio = self.ioclass(newline=None)
430 # The C StringIO decodes newlines in write() calls, but the Python
431 # implementation only does when reading. This function forces them to
432 # be decoded for testing.
433 def force_decode():
434 memio.seek(0)
435 memio.read()
436 self.assertEqual(memio.newlines, None)
437 memio.write("a\n")
438 force_decode()
439 self.assertEqual(memio.newlines, "\n")
440 memio.write("b\r\n")
441 force_decode()
442 self.assertEqual(memio.newlines, ("\n", "\r\n"))
443 memio.write("c\rd")
444 force_decode()
445 self.assertEqual(memio.newlines, ("\r", "\n", "\r\n"))
447 def test_relative_seek(self):
448 memio = self.ioclass()
450 self.assertRaises(IOError, memio.seek, -1, 1)
451 self.assertRaises(IOError, memio.seek, 3, 1)
452 self.assertRaises(IOError, memio.seek, -3, 1)
453 self.assertRaises(IOError, memio.seek, -1, 2)
454 self.assertRaises(IOError, memio.seek, 1, 1)
455 self.assertRaises(IOError, memio.seek, 1, 2)
457 def test_textio_properties(self):
458 memio = self.ioclass()
460 # These are just dummy values but we nevertheless check them for fear
461 # of unexpected breakage.
462 self.assertIsNone(memio.encoding)
463 self.assertIsNone(memio.errors)
464 self.assertFalse(memio.line_buffering)
466 def test_newline_none(self):
467 # newline=None
468 memio = self.ioclass("a\nb\r\nc\rd", newline=None)
469 self.assertEqual(list(memio), ["a\n", "b\n", "c\n", "d"])
470 memio.seek(0)
471 self.assertEqual(memio.read(1), "a")
472 self.assertEqual(memio.read(2), "\nb")
473 self.assertEqual(memio.read(2), "\nc")
474 self.assertEqual(memio.read(1), "\n")
475 memio = self.ioclass(newline=None)
476 self.assertEqual(2, memio.write("a\n"))
477 self.assertEqual(3, memio.write("b\r\n"))
478 self.assertEqual(3, memio.write("c\rd"))
479 memio.seek(0)
480 self.assertEqual(memio.read(), "a\nb\nc\nd")
481 memio = self.ioclass("a\r\nb", newline=None)
482 self.assertEqual(memio.read(3), "a\nb")
484 def test_newline_empty(self):
485 # newline=""
486 memio = self.ioclass("a\nb\r\nc\rd", newline="")
487 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
488 memio.seek(0)
489 self.assertEqual(memio.read(4), "a\nb\r")
490 self.assertEqual(memio.read(2), "\nc")
491 self.assertEqual(memio.read(1), "\r")
492 memio = self.ioclass(newline="")
493 self.assertEqual(2, memio.write("a\n"))
494 self.assertEqual(2, memio.write("b\r"))
495 self.assertEqual(2, memio.write("\nc"))
496 self.assertEqual(2, memio.write("\rd"))
497 memio.seek(0)
498 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
500 def test_newline_lf(self):
501 # newline="\n"
502 memio = self.ioclass("a\nb\r\nc\rd")
503 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
505 def test_newline_cr(self):
506 # newline="\r"
507 memio = self.ioclass("a\nb\r\nc\rd", newline="\r")
508 memio.seek(0)
509 self.assertEqual(memio.read(), "a\rb\r\rc\rd")
510 memio.seek(0)
511 self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
513 def test_newline_crlf(self):
514 # newline="\r\n"
515 memio = self.ioclass("a\nb\r\nc\rd", newline="\r\n")
516 memio.seek(0)
517 self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd")
518 memio.seek(0)
519 self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
521 def test_issue5265(self):
522 # StringIO can duplicate newlines in universal newlines mode
523 memio = self.ioclass("a\r\nb\r\n", newline=None)
524 self.assertEqual(memio.read(5), "a\nb\n")
527 class CBytesIOTest(PyBytesIOTest):
528 ioclass = io.BytesIO
529 UnsupportedOperation = io.UnsupportedOperation
531 class CStringIOTest(PyStringIOTest):
532 ioclass = io.StringIO
533 UnsupportedOperation = io.UnsupportedOperation
535 # XXX: For the Python version of io.StringIO, this is highly
536 # dependent on the encoding used for the underlying buffer.
537 def test_widechar(self):
538 buf = self.buftype("\U0002030a\U00020347")
539 memio = self.ioclass(buf)
541 self.assertEqual(memio.getvalue(), buf)
542 self.assertEqual(memio.write(buf), len(buf))
543 self.assertEqual(memio.tell(), len(buf))
544 self.assertEqual(memio.getvalue(), buf)
545 self.assertEqual(memio.write(buf), len(buf))
546 self.assertEqual(memio.tell(), len(buf) * 2)
547 self.assertEqual(memio.getvalue(), buf + buf)
550 def test_main():
551 tests = [PyBytesIOTest, PyStringIOTest, CBytesIOTest, CStringIOTest]
552 support.run_unittest(*tests)
554 if __name__ == '__main__':
555 test_main()