blob: 1afc3636a01f1335702ab97a7368aff06274cf24 [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
7from test import test_support
8
9import io
10
11try:
12 import _bytesio
13 has_c_implementation = True
14except ImportError:
15 has_c_implementation = False
16
17
18class MemoryTestMixin:
19
20 def write_ops(self, f, t):
21 self.assertEqual(f.write(t("blah.")), 5)
22 self.assertEqual(f.seek(0), 0)
23 self.assertEqual(f.write(t("Hello.")), 6)
24 self.assertEqual(f.tell(), 6)
25 self.assertEqual(f.seek(5), 5)
26 self.assertEqual(f.tell(), 5)
27 self.assertEqual(f.write(t(" world\n\n\n")), 9)
28 self.assertEqual(f.seek(0), 0)
29 self.assertEqual(f.write(t("h")), 1)
30 self.assertEqual(f.truncate(12), 12)
31 self.assertEqual(f.tell(), 12)
32
33 def test_write(self):
34 buf = self.buftype("hello world\n")
35 memio = self.ioclass(buf)
36
37 self.write_ops(memio, self.buftype)
38 self.assertEqual(memio.getvalue(), buf)
39 memio = self.ioclass()
40 self.write_ops(memio, self.buftype)
41 self.assertEqual(memio.getvalue(), buf)
42 self.assertRaises(TypeError, memio.write, None)
43 memio.close()
44 self.assertRaises(ValueError, memio.write, self.buftype(""))
45
46 def test_writelines(self):
47 buf = self.buftype("1234567890")
48 memio = self.ioclass()
49
50 self.assertEqual(memio.writelines([buf] * 100), None)
51 self.assertEqual(memio.getvalue(), buf * 100)
52 memio.writelines([])
53 self.assertEqual(memio.getvalue(), buf * 100)
54 memio = self.ioclass()
55 self.assertRaises(TypeError, memio.writelines, [buf] + [1])
56 self.assertEqual(memio.getvalue(), buf)
57 self.assertRaises(TypeError, memio.writelines, None)
58 memio.close()
59 self.assertRaises(ValueError, memio.writelines, [])
60
61 def test_writelines_error(self):
62 memio = self.ioclass()
63 def error_gen():
64 yield self.buftype('spam')
65 raise KeyboardInterrupt
66
67 self.assertRaises(KeyboardInterrupt, memio.writelines, error_gen())
68
69 def test_truncate(self):
70 buf = self.buftype("1234567890")
71 memio = self.ioclass(buf)
72
73 self.assertRaises(ValueError, memio.truncate, -1)
74 memio.seek(6)
75 self.assertEqual(memio.truncate(), 6)
76 self.assertEqual(memio.getvalue(), buf[:6])
77 self.assertEqual(memio.truncate(4), 4)
78 self.assertEqual(memio.getvalue(), buf[:4])
79 self.assertEqual(memio.tell(), 4)
80 memio.write(buf)
81 self.assertEqual(memio.getvalue(), buf[:4] + buf)
82 pos = memio.tell()
83 self.assertEqual(memio.truncate(None), pos)
84 self.assertEqual(memio.tell(), pos)
85 self.assertRaises(TypeError, memio.truncate, '0')
86 memio.close()
87 self.assertRaises(ValueError, memio.truncate, 0)
88
89 def test_init(self):
90 buf = self.buftype("1234567890")
91 memio = self.ioclass(buf)
92 self.assertEqual(memio.getvalue(), buf)
93 memio = self.ioclass(None)
94 self.assertEqual(memio.getvalue(), self.EOF)
95 memio.__init__(buf * 2)
96 self.assertEqual(memio.getvalue(), buf * 2)
97 memio.__init__(buf)
98 self.assertEqual(memio.getvalue(), buf)
99
100 def test_read(self):
101 buf = self.buftype("1234567890")
102 memio = self.ioclass(buf)
103
104 self.assertEqual(memio.read(0), self.EOF)
105 self.assertEqual(memio.read(1), buf[:1])
106 self.assertEqual(memio.read(4), buf[1:5])
107 self.assertEqual(memio.read(900), buf[5:])
108 self.assertEqual(memio.read(), self.EOF)
109 memio.seek(0)
110 self.assertEqual(memio.read(), buf)
111 self.assertEqual(memio.read(), self.EOF)
112 self.assertEqual(memio.tell(), 10)
113 memio.seek(0)
114 self.assertEqual(memio.read(-1), buf)
115 memio.seek(0)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000116 self.assertEqual(type(memio.read()), type(buf))
Alexandre Vassalotti4833b3c2008-05-06 23:47:23 +0000117 memio.seek(100)
118 self.assertEqual(type(memio.read()), type(buf))
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000119 memio.seek(0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000120 self.assertEqual(memio.read(None), buf)
121 self.assertRaises(TypeError, memio.read, '')
122 memio.close()
123 self.assertRaises(ValueError, memio.read)
124
125 def test_readline(self):
126 buf = self.buftype("1234567890\n")
127 memio = self.ioclass(buf * 2)
128
129 self.assertEqual(memio.readline(0), self.EOF)
130 self.assertEqual(memio.readline(), buf)
131 self.assertEqual(memio.readline(), buf)
132 self.assertEqual(memio.readline(), self.EOF)
133 memio.seek(0)
134 self.assertEqual(memio.readline(5), buf[:5])
135 self.assertEqual(memio.readline(5), buf[5:10])
136 self.assertEqual(memio.readline(5), buf[10:15])
137 memio.seek(0)
138 self.assertEqual(memio.readline(-1), buf)
139 memio.seek(0)
140 self.assertEqual(memio.readline(0), self.EOF)
141
142 buf = self.buftype("1234567890\n")
143 memio = self.ioclass((buf * 3)[:-1])
144 self.assertEqual(memio.readline(), buf)
145 self.assertEqual(memio.readline(), buf)
146 self.assertEqual(memio.readline(), buf[:-1])
147 self.assertEqual(memio.readline(), self.EOF)
148 memio.seek(0)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000149 self.assertEqual(type(memio.readline()), type(buf))
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000150 self.assertEqual(memio.readline(None), buf)
151 self.assertRaises(TypeError, memio.readline, '')
152 memio.close()
153 self.assertRaises(ValueError, memio.readline)
154
155 def test_readlines(self):
156 buf = self.buftype("1234567890\n")
157 memio = self.ioclass(buf * 10)
158
159 self.assertEqual(memio.readlines(), [buf] * 10)
160 memio.seek(5)
161 self.assertEqual(memio.readlines(), [buf[5:]] + [buf] * 9)
162 memio.seek(0)
163 self.assertEqual(memio.readlines(15), [buf] * 2)
164 memio.seek(0)
165 self.assertEqual(memio.readlines(-1), [buf] * 10)
166 memio.seek(0)
167 self.assertEqual(memio.readlines(0), [buf] * 10)
168 memio.seek(0)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000169 self.assertEqual(type(memio.readlines()[0]), type(buf))
170 memio.seek(0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000171 self.assertEqual(memio.readlines(None), [buf] * 10)
172 self.assertRaises(TypeError, memio.readlines, '')
173 memio.close()
174 self.assertRaises(ValueError, memio.readlines)
175
176 def test_iterator(self):
177 buf = self.buftype("1234567890\n")
178 memio = self.ioclass(buf * 10)
179
180 self.assertEqual(iter(memio), memio)
181 self.failUnless(hasattr(memio, '__iter__'))
182 self.failUnless(hasattr(memio, '__next__'))
183 i = 0
184 for line in memio:
185 self.assertEqual(line, buf)
186 i += 1
187 self.assertEqual(i, 10)
188 memio.seek(0)
189 i = 0
190 for line in memio:
191 self.assertEqual(line, buf)
192 i += 1
193 self.assertEqual(i, 10)
194 memio = self.ioclass(buf * 2)
195 memio.close()
196 self.assertRaises(ValueError, memio.__next__)
197
198 def test_getvalue(self):
199 buf = self.buftype("1234567890")
200 memio = self.ioclass(buf)
201
202 self.assertEqual(memio.getvalue(), buf)
203 memio.read()
204 self.assertEqual(memio.getvalue(), buf)
Alexandre Vassalotti5da31eb2008-05-06 20:30:41 +0000205 self.assertEqual(type(memio.getvalue()), type(buf))
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000206 memio = self.ioclass(buf * 1000)
207 self.assertEqual(memio.getvalue()[-3:], self.buftype("890"))
208 memio = self.ioclass(buf)
209 memio.close()
210 self.assertRaises(ValueError, memio.getvalue)
211
212 def test_seek(self):
213 buf = self.buftype("1234567890")
214 memio = self.ioclass(buf)
215
216 memio.read(5)
217 self.assertRaises(ValueError, memio.seek, -1)
218 self.assertRaises(ValueError, memio.seek, 1, -1)
219 self.assertRaises(ValueError, memio.seek, 1, 3)
220 self.assertEqual(memio.seek(0), 0)
221 self.assertEqual(memio.seek(0, 0), 0)
222 self.assertEqual(memio.read(), buf)
223 self.assertEqual(memio.seek(3), 3)
224 self.assertEqual(memio.seek(0, 1), 3)
225 self.assertEqual(memio.read(), buf[3:])
226 self.assertEqual(memio.seek(len(buf)), len(buf))
227 self.assertEqual(memio.read(), self.EOF)
228 memio.seek(len(buf) + 1)
229 self.assertEqual(memio.read(), self.EOF)
230 self.assertEqual(memio.seek(0, 2), len(buf))
231 self.assertEqual(memio.read(), self.EOF)
232 memio.close()
233 self.assertRaises(ValueError, memio.seek, 0)
234
235 def test_overseek(self):
236 buf = self.buftype("1234567890")
237 memio = self.ioclass(buf)
238
239 self.assertEqual(memio.seek(len(buf) + 1), 11)
240 self.assertEqual(memio.read(), self.EOF)
241 self.assertEqual(memio.tell(), 11)
242 self.assertEqual(memio.getvalue(), buf)
243 memio.write(self.EOF)
244 self.assertEqual(memio.getvalue(), buf)
245 memio.write(buf)
246 self.assertEqual(memio.getvalue(), buf + self.buftype('\0') + buf)
247
248 def test_tell(self):
249 buf = self.buftype("1234567890")
250 memio = self.ioclass(buf)
251
252 self.assertEqual(memio.tell(), 0)
253 memio.seek(5)
254 self.assertEqual(memio.tell(), 5)
255 memio.seek(10000)
256 self.assertEqual(memio.tell(), 10000)
257 memio.close()
258 self.assertRaises(ValueError, memio.tell)
259
260 def test_flush(self):
261 buf = self.buftype("1234567890")
262 memio = self.ioclass(buf)
263
264 self.assertEqual(memio.flush(), None)
265
266 def test_flags(self):
267 memio = self.ioclass()
268
269 self.assertEqual(memio.writable(), True)
270 self.assertEqual(memio.readable(), True)
271 self.assertEqual(memio.seekable(), True)
272 self.assertEqual(memio.isatty(), False)
273 self.assertEqual(memio.closed, False)
274 memio.close()
275 self.assertEqual(memio.writable(), True)
276 self.assertEqual(memio.readable(), True)
277 self.assertEqual(memio.seekable(), True)
278 self.assertRaises(ValueError, memio.isatty)
279 self.assertEqual(memio.closed, True)
280
281 def test_subclassing(self):
282 buf = self.buftype("1234567890")
283 def test1():
284 class MemIO(self.ioclass):
285 pass
286 m = MemIO(buf)
287 return m.getvalue()
288 def test2():
289 class MemIO(self.ioclass):
290 def __init__(me, a, b):
291 self.ioclass.__init__(me, a)
292 m = MemIO(buf, None)
293 return m.getvalue()
294 self.assertEqual(test1(), buf)
295 self.assertEqual(test2(), buf)
296
297
298class PyBytesIOTest(MemoryTestMixin, unittest.TestCase):
299 @staticmethod
300 def buftype(s):
301 return s.encode("ascii")
302 ioclass = io._BytesIO
303 EOF = b""
304
305 def test_read1(self):
306 buf = self.buftype("1234567890")
307 memio = self.ioclass(buf)
308
309 self.assertRaises(TypeError, memio.read1)
310 self.assertEqual(memio.read(), buf)
311
312 def test_readinto(self):
313 buf = self.buftype("1234567890")
314 memio = self.ioclass(buf)
315
316 b = bytearray(b"hello")
317 self.assertEqual(memio.readinto(b), 5)
318 self.assertEqual(b, b"12345")
319 self.assertEqual(memio.readinto(b), 5)
320 self.assertEqual(b, b"67890")
321 self.assertEqual(memio.readinto(b), 0)
322 self.assertEqual(b, b"67890")
323 b = bytearray(b"hello world")
324 memio.seek(0)
325 self.assertEqual(memio.readinto(b), 10)
326 self.assertEqual(b, b"1234567890d")
327 b = bytearray(b"")
328 memio.seek(0)
329 self.assertEqual(memio.readinto(b), 0)
330 self.assertEqual(b, b"")
331 self.assertRaises(TypeError, memio.readinto, '')
332 import array
333 a = array.array('b', b"hello world")
334 memio = self.ioclass(buf)
335 memio.readinto(a)
336 self.assertEqual(a.tostring(), b"1234567890d")
337 memio.close()
338 self.assertRaises(ValueError, memio.readinto, b)
339
340 def test_relative_seek(self):
341 buf = self.buftype("1234567890")
342 memio = self.ioclass(buf)
343
344 self.assertEqual(memio.seek(-1, 1), 0)
345 self.assertEqual(memio.seek(3, 1), 3)
346 self.assertEqual(memio.seek(-4, 1), 0)
347 self.assertEqual(memio.seek(-1, 2), 9)
348 self.assertEqual(memio.seek(1, 1), 10)
349 self.assertEqual(memio.seek(1, 2), 11)
350 memio.seek(-3, 2)
351 self.assertEqual(memio.read(), buf[-3:])
352 memio.seek(0)
353 memio.seek(1, 1)
354 self.assertEqual(memio.read(), buf[1:])
355
356 def test_unicode(self):
357 memio = self.ioclass()
358
359 self.assertRaises(TypeError, self.ioclass, "1234567890")
360 self.assertRaises(TypeError, memio.write, "1234567890")
361 self.assertRaises(TypeError, memio.writelines, ["1234567890"])
362
363 def test_bytes_array(self):
364 buf = b"1234567890"
365 import array
366 a = array.array('b', list(buf))
367 memio = self.ioclass(a)
368 self.assertEqual(memio.getvalue(), buf)
369 self.assertEqual(memio.write(a), 10)
370 self.assertEqual(memio.getvalue(), buf)
371
372
373class PyStringIOTest(MemoryTestMixin, unittest.TestCase):
374 buftype = str
375 ioclass = io.StringIO
376 EOF = ""
377
378 def test_relative_seek(self):
379 memio = self.ioclass()
380
381 self.assertRaises(IOError, memio.seek, -1, 1)
382 self.assertRaises(IOError, memio.seek, 3, 1)
383 self.assertRaises(IOError, memio.seek, -3, 1)
384 self.assertRaises(IOError, memio.seek, -1, 2)
385 self.assertRaises(IOError, memio.seek, 1, 1)
386 self.assertRaises(IOError, memio.seek, 1, 2)
387
388 # XXX: For the Python version of io.StringIO, this is highly
389 # dependent on the encoding used for the underlying buffer.
390 # def test_widechar(self):
391 # buf = self.buftype("\U0002030a\U00020347")
392 # memio = self.ioclass(buf)
393 #
394 # self.assertEqual(memio.getvalue(), buf)
395 # self.assertEqual(memio.write(buf), len(buf))
396 # self.assertEqual(memio.tell(), len(buf))
397 # self.assertEqual(memio.getvalue(), buf)
398 # self.assertEqual(memio.write(buf), len(buf))
399 # self.assertEqual(memio.tell(), len(buf) * 2)
400 # self.assertEqual(memio.getvalue(), buf + buf)
401
402if has_c_implementation:
403 class CBytesIOTest(PyBytesIOTest):
404 ioclass = io.BytesIO
405
406def test_main():
407 tests = [PyBytesIOTest, PyStringIOTest]
408 if has_c_implementation:
409 tests.extend([CBytesIOTest])
410 test_support.run_unittest(*tests)
411
412if __name__ == '__main__':
413 test_main()