blob: 0b09ca4ed030e45743e75de151527b64fd0591c0 [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)
116 self.assertEqual(memio.read(None), buf)
117 self.assertRaises(TypeError, memio.read, '')
118 memio.close()
119 self.assertRaises(ValueError, memio.read)
120
121 def test_readline(self):
122 buf = self.buftype("1234567890\n")
123 memio = self.ioclass(buf * 2)
124
125 self.assertEqual(memio.readline(0), self.EOF)
126 self.assertEqual(memio.readline(), buf)
127 self.assertEqual(memio.readline(), buf)
128 self.assertEqual(memio.readline(), self.EOF)
129 memio.seek(0)
130 self.assertEqual(memio.readline(5), buf[:5])
131 self.assertEqual(memio.readline(5), buf[5:10])
132 self.assertEqual(memio.readline(5), buf[10:15])
133 memio.seek(0)
134 self.assertEqual(memio.readline(-1), buf)
135 memio.seek(0)
136 self.assertEqual(memio.readline(0), self.EOF)
137
138 buf = self.buftype("1234567890\n")
139 memio = self.ioclass((buf * 3)[:-1])
140 self.assertEqual(memio.readline(), buf)
141 self.assertEqual(memio.readline(), buf)
142 self.assertEqual(memio.readline(), buf[:-1])
143 self.assertEqual(memio.readline(), self.EOF)
144 memio.seek(0)
145 self.assertEqual(memio.readline(None), buf)
146 self.assertRaises(TypeError, memio.readline, '')
147 memio.close()
148 self.assertRaises(ValueError, memio.readline)
149
150 def test_readlines(self):
151 buf = self.buftype("1234567890\n")
152 memio = self.ioclass(buf * 10)
153
154 self.assertEqual(memio.readlines(), [buf] * 10)
155 memio.seek(5)
156 self.assertEqual(memio.readlines(), [buf[5:]] + [buf] * 9)
157 memio.seek(0)
158 self.assertEqual(memio.readlines(15), [buf] * 2)
159 memio.seek(0)
160 self.assertEqual(memio.readlines(-1), [buf] * 10)
161 memio.seek(0)
162 self.assertEqual(memio.readlines(0), [buf] * 10)
163 memio.seek(0)
164 self.assertEqual(memio.readlines(None), [buf] * 10)
165 self.assertRaises(TypeError, memio.readlines, '')
166 memio.close()
167 self.assertRaises(ValueError, memio.readlines)
168
169 def test_iterator(self):
170 buf = self.buftype("1234567890\n")
171 memio = self.ioclass(buf * 10)
172
173 self.assertEqual(iter(memio), memio)
174 self.failUnless(hasattr(memio, '__iter__'))
175 self.failUnless(hasattr(memio, '__next__'))
176 i = 0
177 for line in memio:
178 self.assertEqual(line, buf)
179 i += 1
180 self.assertEqual(i, 10)
181 memio.seek(0)
182 i = 0
183 for line in memio:
184 self.assertEqual(line, buf)
185 i += 1
186 self.assertEqual(i, 10)
187 memio = self.ioclass(buf * 2)
188 memio.close()
189 self.assertRaises(ValueError, memio.__next__)
190
191 def test_getvalue(self):
192 buf = self.buftype("1234567890")
193 memio = self.ioclass(buf)
194
195 self.assertEqual(memio.getvalue(), buf)
196 memio.read()
197 self.assertEqual(memio.getvalue(), buf)
198 memio = self.ioclass(buf * 1000)
199 self.assertEqual(memio.getvalue()[-3:], self.buftype("890"))
200 memio = self.ioclass(buf)
201 memio.close()
202 self.assertRaises(ValueError, memio.getvalue)
203
204 def test_seek(self):
205 buf = self.buftype("1234567890")
206 memio = self.ioclass(buf)
207
208 memio.read(5)
209 self.assertRaises(ValueError, memio.seek, -1)
210 self.assertRaises(ValueError, memio.seek, 1, -1)
211 self.assertRaises(ValueError, memio.seek, 1, 3)
212 self.assertEqual(memio.seek(0), 0)
213 self.assertEqual(memio.seek(0, 0), 0)
214 self.assertEqual(memio.read(), buf)
215 self.assertEqual(memio.seek(3), 3)
216 self.assertEqual(memio.seek(0, 1), 3)
217 self.assertEqual(memio.read(), buf[3:])
218 self.assertEqual(memio.seek(len(buf)), len(buf))
219 self.assertEqual(memio.read(), self.EOF)
220 memio.seek(len(buf) + 1)
221 self.assertEqual(memio.read(), self.EOF)
222 self.assertEqual(memio.seek(0, 2), len(buf))
223 self.assertEqual(memio.read(), self.EOF)
224 memio.close()
225 self.assertRaises(ValueError, memio.seek, 0)
226
227 def test_overseek(self):
228 buf = self.buftype("1234567890")
229 memio = self.ioclass(buf)
230
231 self.assertEqual(memio.seek(len(buf) + 1), 11)
232 self.assertEqual(memio.read(), self.EOF)
233 self.assertEqual(memio.tell(), 11)
234 self.assertEqual(memio.getvalue(), buf)
235 memio.write(self.EOF)
236 self.assertEqual(memio.getvalue(), buf)
237 memio.write(buf)
238 self.assertEqual(memio.getvalue(), buf + self.buftype('\0') + buf)
239
240 def test_tell(self):
241 buf = self.buftype("1234567890")
242 memio = self.ioclass(buf)
243
244 self.assertEqual(memio.tell(), 0)
245 memio.seek(5)
246 self.assertEqual(memio.tell(), 5)
247 memio.seek(10000)
248 self.assertEqual(memio.tell(), 10000)
249 memio.close()
250 self.assertRaises(ValueError, memio.tell)
251
252 def test_flush(self):
253 buf = self.buftype("1234567890")
254 memio = self.ioclass(buf)
255
256 self.assertEqual(memio.flush(), None)
257
258 def test_flags(self):
259 memio = self.ioclass()
260
261 self.assertEqual(memio.writable(), True)
262 self.assertEqual(memio.readable(), True)
263 self.assertEqual(memio.seekable(), True)
264 self.assertEqual(memio.isatty(), False)
265 self.assertEqual(memio.closed, False)
266 memio.close()
267 self.assertEqual(memio.writable(), True)
268 self.assertEqual(memio.readable(), True)
269 self.assertEqual(memio.seekable(), True)
270 self.assertRaises(ValueError, memio.isatty)
271 self.assertEqual(memio.closed, True)
272
273 def test_subclassing(self):
274 buf = self.buftype("1234567890")
275 def test1():
276 class MemIO(self.ioclass):
277 pass
278 m = MemIO(buf)
279 return m.getvalue()
280 def test2():
281 class MemIO(self.ioclass):
282 def __init__(me, a, b):
283 self.ioclass.__init__(me, a)
284 m = MemIO(buf, None)
285 return m.getvalue()
286 self.assertEqual(test1(), buf)
287 self.assertEqual(test2(), buf)
288
289
290class PyBytesIOTest(MemoryTestMixin, unittest.TestCase):
291 @staticmethod
292 def buftype(s):
293 return s.encode("ascii")
294 ioclass = io._BytesIO
295 EOF = b""
296
297 def test_read1(self):
298 buf = self.buftype("1234567890")
299 memio = self.ioclass(buf)
300
301 self.assertRaises(TypeError, memio.read1)
302 self.assertEqual(memio.read(), buf)
303
304 def test_readinto(self):
305 buf = self.buftype("1234567890")
306 memio = self.ioclass(buf)
307
308 b = bytearray(b"hello")
309 self.assertEqual(memio.readinto(b), 5)
310 self.assertEqual(b, b"12345")
311 self.assertEqual(memio.readinto(b), 5)
312 self.assertEqual(b, b"67890")
313 self.assertEqual(memio.readinto(b), 0)
314 self.assertEqual(b, b"67890")
315 b = bytearray(b"hello world")
316 memio.seek(0)
317 self.assertEqual(memio.readinto(b), 10)
318 self.assertEqual(b, b"1234567890d")
319 b = bytearray(b"")
320 memio.seek(0)
321 self.assertEqual(memio.readinto(b), 0)
322 self.assertEqual(b, b"")
323 self.assertRaises(TypeError, memio.readinto, '')
324 import array
325 a = array.array('b', b"hello world")
326 memio = self.ioclass(buf)
327 memio.readinto(a)
328 self.assertEqual(a.tostring(), b"1234567890d")
329 memio.close()
330 self.assertRaises(ValueError, memio.readinto, b)
331
332 def test_relative_seek(self):
333 buf = self.buftype("1234567890")
334 memio = self.ioclass(buf)
335
336 self.assertEqual(memio.seek(-1, 1), 0)
337 self.assertEqual(memio.seek(3, 1), 3)
338 self.assertEqual(memio.seek(-4, 1), 0)
339 self.assertEqual(memio.seek(-1, 2), 9)
340 self.assertEqual(memio.seek(1, 1), 10)
341 self.assertEqual(memio.seek(1, 2), 11)
342 memio.seek(-3, 2)
343 self.assertEqual(memio.read(), buf[-3:])
344 memio.seek(0)
345 memio.seek(1, 1)
346 self.assertEqual(memio.read(), buf[1:])
347
348 def test_unicode(self):
349 memio = self.ioclass()
350
351 self.assertRaises(TypeError, self.ioclass, "1234567890")
352 self.assertRaises(TypeError, memio.write, "1234567890")
353 self.assertRaises(TypeError, memio.writelines, ["1234567890"])
354
355 def test_bytes_array(self):
356 buf = b"1234567890"
357 import array
358 a = array.array('b', list(buf))
359 memio = self.ioclass(a)
360 self.assertEqual(memio.getvalue(), buf)
361 self.assertEqual(memio.write(a), 10)
362 self.assertEqual(memio.getvalue(), buf)
363
364
365class PyStringIOTest(MemoryTestMixin, unittest.TestCase):
366 buftype = str
367 ioclass = io.StringIO
368 EOF = ""
369
370 def test_relative_seek(self):
371 memio = self.ioclass()
372
373 self.assertRaises(IOError, memio.seek, -1, 1)
374 self.assertRaises(IOError, memio.seek, 3, 1)
375 self.assertRaises(IOError, memio.seek, -3, 1)
376 self.assertRaises(IOError, memio.seek, -1, 2)
377 self.assertRaises(IOError, memio.seek, 1, 1)
378 self.assertRaises(IOError, memio.seek, 1, 2)
379
380 # XXX: For the Python version of io.StringIO, this is highly
381 # dependent on the encoding used for the underlying buffer.
382 # def test_widechar(self):
383 # buf = self.buftype("\U0002030a\U00020347")
384 # memio = self.ioclass(buf)
385 #
386 # self.assertEqual(memio.getvalue(), buf)
387 # self.assertEqual(memio.write(buf), len(buf))
388 # self.assertEqual(memio.tell(), len(buf))
389 # self.assertEqual(memio.getvalue(), buf)
390 # self.assertEqual(memio.write(buf), len(buf))
391 # self.assertEqual(memio.tell(), len(buf) * 2)
392 # self.assertEqual(memio.getvalue(), buf + buf)
393
394if has_c_implementation:
395 class CBytesIOTest(PyBytesIOTest):
396 ioclass = io.BytesIO
397
398def test_main():
399 tests = [PyBytesIOTest, PyStringIOTest]
400 if has_c_implementation:
401 tests.extend([CBytesIOTest])
402 test_support.run_unittest(*tests)
403
404if __name__ == '__main__':
405 test_main()