blob: dffa4b56eb6319bd52b12ac3dda2c4032bf07ef7 [file] [log] [blame]
Antoine Pitrou47a5f482009-06-12 20:41:52 +00001# NOTE: this file tests the new `io` library backported from Python 3.x.
2# Similar tests for the builtin file object can be found in test_file2k.py.
3
Antoine Pitrou19690592009-06-12 20:14:08 +00004from __future__ import print_function
5
Martin v. Löwisf90ae202002-06-11 06:22:31 +00006import sys
Fred Drake2ec80fa2000-10-23 16:59:35 +00007import os
Georg Brandl442b49e2006-06-08 14:50:53 +00008import unittest
Neal Norwitz62f5a9d2002-04-01 00:09:00 +00009from array import array
Raymond Hettingercb87bc82004-05-31 00:35:52 +000010from weakref import proxy
Fred Drake2ec80fa2000-10-23 16:59:35 +000011
Antoine Pitrou19690592009-06-12 20:14:08 +000012import io
13import _pyio as pyio
14
Georg Brandla4f46e12010-02-07 17:03:15 +000015from test.test_support import TESTFN, run_unittest
Marc-André Lemburgfa44d792000-08-25 22:37:31 +000016from UserList import UserList
17
Georg Brandl442b49e2006-06-08 14:50:53 +000018class AutoFileTests(unittest.TestCase):
19 # file tests for which a test file is automatically set up
Raymond Hettingercb87bc82004-05-31 00:35:52 +000020
Georg Brandl442b49e2006-06-08 14:50:53 +000021 def setUp(self):
Antoine Pitrou19690592009-06-12 20:14:08 +000022 self.f = self.open(TESTFN, 'wb')
Tim Peters015dd822003-05-04 04:16:52 +000023
Georg Brandl442b49e2006-06-08 14:50:53 +000024 def tearDown(self):
Tim Petersdbb82f62006-06-09 03:51:41 +000025 if self.f:
26 self.f.close()
27 os.remove(TESTFN)
Georg Brandl442b49e2006-06-08 14:50:53 +000028
29 def testWeakRefs(self):
30 # verify weak references
31 p = proxy(self.f)
Antoine Pitrou19690592009-06-12 20:14:08 +000032 p.write(b'teststring')
Ezio Melotti2623a372010-11-21 13:34:58 +000033 self.assertEqual(self.f.tell(), p.tell())
Georg Brandl442b49e2006-06-08 14:50:53 +000034 self.f.close()
35 self.f = None
36 self.assertRaises(ReferenceError, getattr, p, 'tell')
37
38 def testAttributes(self):
39 # verify expected attributes exist
40 f = self.f
Georg Brandl442b49e2006-06-08 14:50:53 +000041 f.name # merely shouldn't blow up
42 f.mode # ditto
43 f.closed # ditto
44
Georg Brandl442b49e2006-06-08 14:50:53 +000045 def testReadinto(self):
46 # verify readinto
Antoine Pitrou19690592009-06-12 20:14:08 +000047 self.f.write(b'12')
Georg Brandl442b49e2006-06-08 14:50:53 +000048 self.f.close()
Antoine Pitrou19690592009-06-12 20:14:08 +000049 a = array('b', b'x'*10)
50 self.f = self.open(TESTFN, 'rb')
Georg Brandl442b49e2006-06-08 14:50:53 +000051 n = self.f.readinto(a)
Ezio Melotti2623a372010-11-21 13:34:58 +000052 self.assertEqual(b'12', a.tostring()[:n])
Antoine Pitrou19690592009-06-12 20:14:08 +000053
54 def testReadinto_text(self):
55 # verify readinto refuses text files
56 a = array('b', b'x'*10)
57 self.f.close()
58 self.f = self.open(TESTFN, 'r')
59 if hasattr(self.f, "readinto"):
60 self.assertRaises(TypeError, self.f.readinto, a)
Georg Brandl442b49e2006-06-08 14:50:53 +000061
62 def testWritelinesUserList(self):
63 # verify writelines with instance sequence
Antoine Pitrou19690592009-06-12 20:14:08 +000064 l = UserList([b'1', b'2'])
Georg Brandl442b49e2006-06-08 14:50:53 +000065 self.f.writelines(l)
66 self.f.close()
Antoine Pitrou19690592009-06-12 20:14:08 +000067 self.f = self.open(TESTFN, 'rb')
Georg Brandl442b49e2006-06-08 14:50:53 +000068 buf = self.f.read()
Ezio Melotti2623a372010-11-21 13:34:58 +000069 self.assertEqual(buf, b'12')
Georg Brandl442b49e2006-06-08 14:50:53 +000070
71 def testWritelinesIntegers(self):
72 # verify writelines with integers
73 self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
74
75 def testWritelinesIntegersUserList(self):
76 # verify writelines with integers in UserList
77 l = UserList([1,2,3])
78 self.assertRaises(TypeError, self.f.writelines, l)
79
80 def testWritelinesNonString(self):
81 # verify writelines with non-string object
Tim Petersdbb82f62006-06-09 03:51:41 +000082 class NonString:
83 pass
Georg Brandl442b49e2006-06-08 14:50:53 +000084
Tim Petersdbb82f62006-06-09 03:51:41 +000085 self.assertRaises(TypeError, self.f.writelines,
86 [NonString(), NonString()])
Georg Brandl442b49e2006-06-08 14:50:53 +000087
Georg Brandl442b49e2006-06-08 14:50:53 +000088 def testErrors(self):
89 f = self.f
Ezio Melotti2623a372010-11-21 13:34:58 +000090 self.assertEqual(f.name, TESTFN)
Benjamin Peterson5c8da862009-06-30 22:57:08 +000091 self.assertTrue(not f.isatty())
92 self.assertTrue(not f.closed)
Tim Peters520d8dd2006-06-09 02:11:02 +000093
Antoine Pitrou19690592009-06-12 20:14:08 +000094 if hasattr(f, "readinto"):
95 self.assertRaises((IOError, TypeError), f.readinto, "")
Georg Brandl442b49e2006-06-08 14:50:53 +000096 f.close()
Benjamin Peterson5c8da862009-06-30 22:57:08 +000097 self.assertTrue(f.closed)
Georg Brandl442b49e2006-06-08 14:50:53 +000098
99 def testMethods(self):
Antoine Pitrou19690592009-06-12 20:14:08 +0000100 methods = [('fileno', ()),
101 ('flush', ()),
102 ('isatty', ()),
103 ('next', ()),
104 ('read', ()),
105 ('write', (b"",)),
106 ('readline', ()),
107 ('readlines', ()),
108 ('seek', (0,)),
109 ('tell', ()),
110 ('write', (b"",)),
111 ('writelines', ([],)),
112 ('__iter__', ()),
113 ]
114 if not sys.platform.startswith('atheos'):
115 methods.append(('truncate', ()))
Georg Brandl442b49e2006-06-08 14:50:53 +0000116
Georg Brandle7ec81f2006-06-09 18:29:52 +0000117 # __exit__ should close the file
118 self.f.__exit__(None, None, None)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000119 self.assertTrue(self.f.closed)
Georg Brandl442b49e2006-06-08 14:50:53 +0000120
Antoine Pitrou19690592009-06-12 20:14:08 +0000121 for methodname, args in methods:
Georg Brandl442b49e2006-06-08 14:50:53 +0000122 method = getattr(self.f, methodname)
123 # should raise on closed file
Antoine Pitrou19690592009-06-12 20:14:08 +0000124 self.assertRaises(ValueError, method, *args)
Georg Brandl442b49e2006-06-08 14:50:53 +0000125
Georg Brandle7ec81f2006-06-09 18:29:52 +0000126 # file is closed, __exit__ shouldn't do anything
Ezio Melotti2623a372010-11-21 13:34:58 +0000127 self.assertEqual(self.f.__exit__(None, None, None), None)
Georg Brandle7ec81f2006-06-09 18:29:52 +0000128 # it must also return None if an exception was given
129 try:
Ezio Melottidde5b942010-02-03 05:37:26 +0000130 1 // 0
Georg Brandle7ec81f2006-06-09 18:29:52 +0000131 except:
Ezio Melotti2623a372010-11-21 13:34:58 +0000132 self.assertEqual(self.f.__exit__(*sys.exc_info()), None)
Georg Brandle7ec81f2006-06-09 18:29:52 +0000133
Skip Montanarof205c132008-12-23 03:30:15 +0000134 def testReadWhenWriting(self):
135 self.assertRaises(IOError, self.f.read)
Georg Brandl442b49e2006-06-08 14:50:53 +0000136
Antoine Pitrou19690592009-06-12 20:14:08 +0000137class CAutoFileTests(AutoFileTests):
138 open = io.open
Georg Brandl442b49e2006-06-08 14:50:53 +0000139
Antoine Pitrou19690592009-06-12 20:14:08 +0000140class PyAutoFileTests(AutoFileTests):
141 open = staticmethod(pyio.open)
142
143
144class OtherFileTests(unittest.TestCase):
Benjamin Petersonfe231b02008-12-29 17:47:42 +0000145
Georg Brandl442b49e2006-06-08 14:50:53 +0000146 def testModeStrings(self):
147 # check invalid mode strings
148 for mode in ("", "aU", "wU+"):
149 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000150 f = self.open(TESTFN, mode)
Georg Brandl442b49e2006-06-08 14:50:53 +0000151 except ValueError:
152 pass
153 else:
154 f.close()
155 self.fail('%r is an invalid file mode' % mode)
156
157 def testStdin(self):
158 # This causes the interpreter to exit on OSF1 v5.1.
159 if sys.platform != 'osf1V5':
Antoine Pitrou19690592009-06-12 20:14:08 +0000160 self.assertRaises((IOError, ValueError), sys.stdin.seek, -1)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000161 else:
Antoine Pitrou19690592009-06-12 20:14:08 +0000162 print((
Georg Brandl442b49e2006-06-08 14:50:53 +0000163 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
Antoine Pitrou19690592009-06-12 20:14:08 +0000164 ' Test manually.'), file=sys.__stdout__)
165 self.assertRaises((IOError, ValueError), sys.stdin.truncate)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000166
Georg Brandl442b49e2006-06-08 14:50:53 +0000167 def testBadModeArgument(self):
168 # verify that we get a sensible error message for bad mode argument
169 bad_mode = "qwerty"
Tim Peterscffcfed2006-02-14 17:41:18 +0000170 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000171 f = self.open(TESTFN, bad_mode)
172 except ValueError as msg:
173 if msg.args[0] != 0:
Georg Brandl442b49e2006-06-08 14:50:53 +0000174 s = str(msg)
Ezio Melotti187f93d2010-03-17 14:22:34 +0000175 if TESTFN in s or bad_mode not in s:
Georg Brandl442b49e2006-06-08 14:50:53 +0000176 self.fail("bad error message for invalid mode: %s" % s)
Antoine Pitrou19690592009-06-12 20:14:08 +0000177 # if msg.args[0] == 0, we're probably on Windows where there may be
Georg Brandl442b49e2006-06-08 14:50:53 +0000178 # no obvious way to discover why open() failed.
179 else:
180 f.close()
181 self.fail("no error for invalid mode: %s" % bad_mode)
182
183 def testSetBufferSize(self):
184 # make sure that explicitly setting the buffer size doesn't cause
185 # misbehaviour especially with repeated close() calls
186 for s in (-1, 0, 1, 512):
187 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000188 f = self.open(TESTFN, 'wb', s)
189 f.write(str(s).encode("ascii"))
Georg Brandl442b49e2006-06-08 14:50:53 +0000190 f.close()
191 f.close()
Antoine Pitrou19690592009-06-12 20:14:08 +0000192 f = self.open(TESTFN, 'rb', s)
193 d = int(f.read().decode("ascii"))
Georg Brandl442b49e2006-06-08 14:50:53 +0000194 f.close()
195 f.close()
Antoine Pitrou19690592009-06-12 20:14:08 +0000196 except IOError as msg:
Georg Brandl442b49e2006-06-08 14:50:53 +0000197 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
Ezio Melotti2623a372010-11-21 13:34:58 +0000198 self.assertEqual(d, s)
Georg Brandl442b49e2006-06-08 14:50:53 +0000199
200 def testTruncateOnWindows(self):
Antoine Pitrou19690592009-06-12 20:14:08 +0000201 # SF bug <http://www.python.org/sf/801631>
202 # "file.truncate fault on windows"
Georg Brandl442b49e2006-06-08 14:50:53 +0000203
Antoine Pitrou19690592009-06-12 20:14:08 +0000204 os.unlink(TESTFN)
205 f = self.open(TESTFN, 'wb')
206
207 try:
208 f.write(b'12345678901') # 11 bytes
Georg Brandl442b49e2006-06-08 14:50:53 +0000209 f.close()
210
Antoine Pitrou19690592009-06-12 20:14:08 +0000211 f = self.open(TESTFN,'rb+')
Georg Brandl442b49e2006-06-08 14:50:53 +0000212 data = f.read(5)
Antoine Pitrou19690592009-06-12 20:14:08 +0000213 if data != b'12345':
Georg Brandl442b49e2006-06-08 14:50:53 +0000214 self.fail("Read on file opened for update failed %r" % data)
215 if f.tell() != 5:
216 self.fail("File pos after read wrong %d" % f.tell())
217
218 f.truncate()
219 if f.tell() != 5:
220 self.fail("File pos after ftruncate wrong %d" % f.tell())
221
222 f.close()
223 size = os.path.getsize(TESTFN)
224 if size != 5:
225 self.fail("File size after ftruncate wrong %d" % size)
Georg Brandl442b49e2006-06-08 14:50:53 +0000226 finally:
Antoine Pitrou19690592009-06-12 20:14:08 +0000227 f.close()
Georg Brandl442b49e2006-06-08 14:50:53 +0000228 os.unlink(TESTFN)
229
230 def testIteration(self):
Tim Petersdbb82f62006-06-09 03:51:41 +0000231 # Test the complex interaction when mixing file-iteration and the
Antoine Pitrou19690592009-06-12 20:14:08 +0000232 # various read* methods.
Georg Brandl442b49e2006-06-08 14:50:53 +0000233 dataoffset = 16384
Antoine Pitrou19690592009-06-12 20:14:08 +0000234 filler = b"ham\n"
Georg Brandl442b49e2006-06-08 14:50:53 +0000235 assert not dataoffset % len(filler), \
236 "dataoffset must be multiple of len(filler)"
237 nchunks = dataoffset // len(filler)
238 testlines = [
Antoine Pitrou19690592009-06-12 20:14:08 +0000239 b"spam, spam and eggs\n",
240 b"eggs, spam, ham and spam\n",
241 b"saussages, spam, spam and eggs\n",
242 b"spam, ham, spam and eggs\n",
243 b"spam, spam, spam, spam, spam, ham, spam\n",
244 b"wonderful spaaaaaam.\n"
Georg Brandl442b49e2006-06-08 14:50:53 +0000245 ]
246 methods = [("readline", ()), ("read", ()), ("readlines", ()),
Antoine Pitrou19690592009-06-12 20:14:08 +0000247 ("readinto", (array("b", b" "*100),))]
Georg Brandl442b49e2006-06-08 14:50:53 +0000248
249 try:
250 # Prepare the testfile
Antoine Pitrou19690592009-06-12 20:14:08 +0000251 bag = self.open(TESTFN, "wb")
Georg Brandl442b49e2006-06-08 14:50:53 +0000252 bag.write(filler * nchunks)
253 bag.writelines(testlines)
254 bag.close()
255 # Test for appropriate errors mixing read* and iteration
256 for methodname, args in methods:
Antoine Pitrou19690592009-06-12 20:14:08 +0000257 f = self.open(TESTFN, 'rb')
258 if next(f) != filler:
Georg Brandl442b49e2006-06-08 14:50:53 +0000259 self.fail, "Broken testfile"
260 meth = getattr(f, methodname)
Antoine Pitrou19690592009-06-12 20:14:08 +0000261 meth(*args) # This simply shouldn't fail
Georg Brandl442b49e2006-06-08 14:50:53 +0000262 f.close()
263
Tim Petersdbb82f62006-06-09 03:51:41 +0000264 # Test to see if harmless (by accident) mixing of read* and
265 # iteration still works. This depends on the size of the internal
266 # iteration buffer (currently 8192,) but we can test it in a
267 # flexible manner. Each line in the bag o' ham is 4 bytes
268 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
269 # exactly on the buffer boundary for any power-of-2 buffersize
270 # between 4 and 16384 (inclusive).
Antoine Pitrou19690592009-06-12 20:14:08 +0000271 f = self.open(TESTFN, 'rb')
Georg Brandl442b49e2006-06-08 14:50:53 +0000272 for i in range(nchunks):
Antoine Pitrou19690592009-06-12 20:14:08 +0000273 next(f)
Georg Brandl442b49e2006-06-08 14:50:53 +0000274 testline = testlines.pop(0)
275 try:
276 line = f.readline()
277 except ValueError:
278 self.fail("readline() after next() with supposedly empty "
279 "iteration-buffer failed anyway")
280 if line != testline:
281 self.fail("readline() after next() with empty buffer "
282 "failed. Got %r, expected %r" % (line, testline))
283 testline = testlines.pop(0)
Antoine Pitrou19690592009-06-12 20:14:08 +0000284 buf = array("b", b"\x00" * len(testline))
Georg Brandl442b49e2006-06-08 14:50:53 +0000285 try:
286 f.readinto(buf)
287 except ValueError:
288 self.fail("readinto() after next() with supposedly empty "
289 "iteration-buffer failed anyway")
290 line = buf.tostring()
291 if line != testline:
292 self.fail("readinto() after next() with empty buffer "
293 "failed. Got %r, expected %r" % (line, testline))
294
295 testline = testlines.pop(0)
296 try:
297 line = f.read(len(testline))
298 except ValueError:
299 self.fail("read() after next() with supposedly empty "
300 "iteration-buffer failed anyway")
301 if line != testline:
302 self.fail("read() after next() with empty buffer "
303 "failed. Got %r, expected %r" % (line, testline))
304 try:
305 lines = f.readlines()
306 except ValueError:
307 self.fail("readlines() after next() with supposedly empty "
308 "iteration-buffer failed anyway")
309 if lines != testlines:
310 self.fail("readlines() after next() with empty buffer "
311 "failed. Got %r, expected %r" % (line, testline))
312 # Reading after iteration hit EOF shouldn't hurt either
Antoine Pitrou19690592009-06-12 20:14:08 +0000313 f = self.open(TESTFN, 'rb')
Georg Brandl442b49e2006-06-08 14:50:53 +0000314 try:
315 for line in f:
316 pass
317 try:
318 f.readline()
319 f.readinto(buf)
320 f.read()
321 f.readlines()
322 except ValueError:
323 self.fail("read* failed after next() consumed file")
324 finally:
325 f.close()
326 finally:
327 os.unlink(TESTFN)
328
Antoine Pitrou19690592009-06-12 20:14:08 +0000329class COtherFileTests(OtherFileTests):
330 open = io.open
Georg Brandlad61bc82008-02-23 15:11:18 +0000331
Antoine Pitrou19690592009-06-12 20:14:08 +0000332class PyOtherFileTests(OtherFileTests):
333 open = staticmethod(pyio.open)
Jeffrey Yasskin2d873bd2008-12-08 18:55:24 +0000334
Gregory P. Smithaa63d0d2008-04-06 23:11:17 +0000335
Georg Brandl442b49e2006-06-08 14:50:53 +0000336def test_main():
Neal Norwitzc9778a82006-06-09 05:54:18 +0000337 # Historically, these tests have been sloppy about removing TESTFN.
338 # So get rid of it no matter what.
Tim Peters0556e9b2006-06-09 04:02:06 +0000339 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000340 run_unittest(CAutoFileTests, PyAutoFileTests,
341 COtherFileTests, PyOtherFileTests)
Tim Peters0556e9b2006-06-09 04:02:06 +0000342 finally:
343 if os.path.exists(TESTFN):
344 os.unlink(TESTFN)
Georg Brandl442b49e2006-06-08 14:50:53 +0000345
346if __name__ == '__main__':
347 test_main()