blob: bb0da792f55c6d538a652c531d66e6b40d6740a9 [file] [log] [blame]
Martin v. Löwisf90ae202002-06-11 06:22:31 +00001import sys
Fred Drake2ec80fa2000-10-23 16:59:35 +00002import os
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003import unittest
Neal Norwitz62f5a9d2002-04-01 00:09:00 +00004from array import array
Raymond Hettingercb87bc82004-05-31 00:35:52 +00005from weakref import proxy
Fred Drake2ec80fa2000-10-23 16:59:35 +00006
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00007import io
8import _pyio as pyio
9
Georg Brandl1b37e872010-03-14 10:45:50 +000010from test.support import TESTFN, run_unittest
Raymond Hettinger53dbe392008-02-12 20:03:09 +000011from collections import UserList
Marc-André Lemburgfa44d792000-08-25 22:37:31 +000012
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000013class AutoFileTests(unittest.TestCase):
14 # file tests for which a test file is automatically set up
Raymond Hettingercb87bc82004-05-31 00:35:52 +000015
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000016 def setUp(self):
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000017 self.f = self.open(TESTFN, 'wb')
Tim Peters015dd822003-05-04 04:16:52 +000018
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000019 def tearDown(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000020 if self.f:
21 self.f.close()
22 os.remove(TESTFN)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000023
24 def testWeakRefs(self):
25 # verify weak references
26 p = proxy(self.f)
Guido van Rossume22905a2007-08-27 23:09:25 +000027 p.write(b'teststring')
Ezio Melottib3aedd42010-11-20 19:04:17 +000028 self.assertEqual(self.f.tell(), p.tell())
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000029 self.f.close()
30 self.f = None
31 self.assertRaises(ReferenceError, getattr, p, 'tell')
32
33 def testAttributes(self):
34 # verify expected attributes exist
35 f = self.f
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000036 f.name # merely shouldn't blow up
37 f.mode # ditto
38 f.closed # ditto
39
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000040 def testReadinto(self):
41 # verify readinto
Guido van Rossume22905a2007-08-27 23:09:25 +000042 self.f.write(b'12')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000043 self.f.close()
Guido van Rossum7165cb12007-07-10 06:54:34 +000044 a = array('b', b'x'*10)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000045 self.f = self.open(TESTFN, 'rb')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000046 n = self.f.readinto(a)
Ezio Melottib3aedd42010-11-20 19:04:17 +000047 self.assertEqual(b'12', a.tobytes()[:n])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000048
49 def testReadinto_text(self):
50 # verify readinto refuses text files
Guido van Rossum7165cb12007-07-10 06:54:34 +000051 a = array('b', b'x'*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000052 self.f.close()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000053 self.f = self.open(TESTFN, 'r')
Guido van Rossum7165cb12007-07-10 06:54:34 +000054 if hasattr(self.f, "readinto"):
55 self.assertRaises(TypeError, self.f.readinto, a)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000056
57 def testWritelinesUserList(self):
58 # verify writelines with instance sequence
Guido van Rossum7165cb12007-07-10 06:54:34 +000059 l = UserList([b'1', b'2'])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000060 self.f.writelines(l)
61 self.f.close()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000062 self.f = self.open(TESTFN, 'rb')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000063 buf = self.f.read()
Ezio Melottib3aedd42010-11-20 19:04:17 +000064 self.assertEqual(buf, b'12')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000065
66 def testWritelinesIntegers(self):
67 # verify writelines with integers
68 self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
69
70 def testWritelinesIntegersUserList(self):
71 # verify writelines with integers in UserList
72 l = UserList([1,2,3])
73 self.assertRaises(TypeError, self.f.writelines, l)
74
75 def testWritelinesNonString(self):
76 # verify writelines with non-string object
Thomas Wouters0e3f5912006-08-11 14:57:12 +000077 class NonString:
78 pass
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000079
Thomas Wouters0e3f5912006-08-11 14:57:12 +000080 self.assertRaises(TypeError, self.f.writelines,
81 [NonString(), NonString()])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000082
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000083 def testErrors(self):
84 f = self.f
Ezio Melottib3aedd42010-11-20 19:04:17 +000085 self.assertEqual(f.name, TESTFN)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000086 self.assertTrue(not f.isatty())
87 self.assertTrue(not f.closed)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000088
Guido van Rossum7165cb12007-07-10 06:54:34 +000089 if hasattr(f, "readinto"):
90 self.assertRaises((IOError, TypeError), f.readinto, "")
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000091 f.close()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000092 self.assertTrue(f.closed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000093
94 def testMethods(self):
Guido van Rossum4b5386f2007-07-10 09:12:49 +000095 methods = [('fileno', ()),
96 ('flush', ()),
97 ('isatty', ()),
98 ('__next__', ()),
99 ('read', ()),
100 ('write', (b"",)),
101 ('readline', ()),
102 ('readlines', ()),
103 ('seek', (0,)),
104 ('tell', ()),
105 ('write', (b"",)),
106 ('writelines', ([],)),
107 ('__iter__', ()),
108 ]
Antoine Pitrou6103ab12009-10-24 20:11:21 +0000109 methods.append(('truncate', ()))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000110
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000111 # __exit__ should close the file
112 self.f.__exit__(None, None, None)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000113 self.assertTrue(self.f.closed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000114
Guido van Rossum4b5386f2007-07-10 09:12:49 +0000115 for methodname, args in methods:
116 method = getattr(self.f, methodname)
117 # should raise on closed file
118 self.assertRaises(ValueError, method, *args)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000119
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000120 # file is closed, __exit__ shouldn't do anything
Ezio Melottib3aedd42010-11-20 19:04:17 +0000121 self.assertEqual(self.f.__exit__(None, None, None), None)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000122 # it must also return None if an exception was given
123 try:
124 1/0
125 except:
Ezio Melottib3aedd42010-11-20 19:04:17 +0000126 self.assertEqual(self.f.__exit__(*sys.exc_info()), None)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000127
Skip Montanaro80072cb2008-12-23 03:51:14 +0000128 def testReadWhenWriting(self):
129 self.assertRaises(IOError, self.f.read)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000130
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000131class CAutoFileTests(AutoFileTests):
132 open = io.open
133
134class PyAutoFileTests(AutoFileTests):
135 open = staticmethod(pyio.open)
136
137
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000138class OtherFileTests(unittest.TestCase):
139
140 def testModeStrings(self):
141 # check invalid mode strings
142 for mode in ("", "aU", "wU+"):
143 try:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000144 f = self.open(TESTFN, mode)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000145 except ValueError:
146 pass
147 else:
148 f.close()
149 self.fail('%r is an invalid file mode' % mode)
150
151 def testStdin(self):
152 # This causes the interpreter to exit on OSF1 v5.1.
153 if sys.platform != 'osf1V5':
Guido van Rossum535a5ef2007-07-10 20:59:22 +0000154 self.assertRaises((IOError, ValueError), sys.stdin.seek, -1)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000155 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000156 print((
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000157 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000158 ' Test manually.'), file=sys.__stdout__)
Guido van Rossum535a5ef2007-07-10 20:59:22 +0000159 self.assertRaises((IOError, ValueError), sys.stdin.truncate)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000160
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000161 def testBadModeArgument(self):
162 # verify that we get a sensible error message for bad mode argument
163 bad_mode = "qwerty"
Tim Peterscffcfed2006-02-14 17:41:18 +0000164 try:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000165 f = self.open(TESTFN, bad_mode)
Guido van Rossumb940e112007-01-10 16:19:56 +0000166 except ValueError as msg:
Brett Cannonca477b22007-03-21 22:26:20 +0000167 if msg.args[0] != 0:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000168 s = str(msg)
Ezio Melotti7fb4da72010-03-18 12:29:13 +0000169 if TESTFN in s or bad_mode not in s:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000170 self.fail("bad error message for invalid mode: %s" % s)
Georg Brandl50da60c2008-01-06 21:38:54 +0000171 # if msg.args[0] == 0, we're probably on Windows where there may be
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000172 # no obvious way to discover why open() failed.
173 else:
174 f.close()
175 self.fail("no error for invalid mode: %s" % bad_mode)
176
177 def testSetBufferSize(self):
178 # make sure that explicitly setting the buffer size doesn't cause
179 # misbehaviour especially with repeated close() calls
180 for s in (-1, 0, 1, 512):
181 try:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000182 f = self.open(TESTFN, 'wb', s)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000183 f.write(str(s).encode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000184 f.close()
185 f.close()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000186 f = self.open(TESTFN, 'rb', s)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000187 d = int(f.read().decode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000188 f.close()
189 f.close()
Guido van Rossumb940e112007-01-10 16:19:56 +0000190 except IOError as msg:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000191 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000192 self.assertEqual(d, s)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000193
194 def testTruncateOnWindows(self):
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000195 # SF bug <http://www.python.org/sf/801631>
196 # "file.truncate fault on windows"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000197
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000198 os.unlink(TESTFN)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000199 f = self.open(TESTFN, 'wb')
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000200
201 try:
Guido van Rossum7165cb12007-07-10 06:54:34 +0000202 f.write(b'12345678901') # 11 bytes
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000203 f.close()
204
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000205 f = self.open(TESTFN,'rb+')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000206 data = f.read(5)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000207 if data != b'12345':
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000208 self.fail("Read on file opened for update failed %r" % data)
209 if f.tell() != 5:
210 self.fail("File pos after read wrong %d" % f.tell())
211
212 f.truncate()
213 if f.tell() != 5:
214 self.fail("File pos after ftruncate wrong %d" % f.tell())
215
216 f.close()
217 size = os.path.getsize(TESTFN)
218 if size != 5:
219 self.fail("File size after ftruncate wrong %d" % size)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000220 finally:
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000221 f.close()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000222 os.unlink(TESTFN)
223
224 def testIteration(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000225 # Test the complex interaction when mixing file-iteration and the
Guido van Rossum7165cb12007-07-10 06:54:34 +0000226 # various read* methods.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000227 dataoffset = 16384
Guido van Rossume22905a2007-08-27 23:09:25 +0000228 filler = b"ham\n"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000229 assert not dataoffset % len(filler), \
230 "dataoffset must be multiple of len(filler)"
231 nchunks = dataoffset // len(filler)
232 testlines = [
Guido van Rossum7165cb12007-07-10 06:54:34 +0000233 b"spam, spam and eggs\n",
234 b"eggs, spam, ham and spam\n",
235 b"saussages, spam, spam and eggs\n",
236 b"spam, ham, spam and eggs\n",
237 b"spam, spam, spam, spam, spam, ham, spam\n",
238 b"wonderful spaaaaaam.\n"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000239 ]
240 methods = [("readline", ()), ("read", ()), ("readlines", ()),
Guido van Rossum7165cb12007-07-10 06:54:34 +0000241 ("readinto", (array("b", b" "*100),))]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000242
243 try:
244 # Prepare the testfile
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000245 bag = self.open(TESTFN, "wb")
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000246 bag.write(filler * nchunks)
247 bag.writelines(testlines)
248 bag.close()
249 # Test for appropriate errors mixing read* and iteration
250 for methodname, args in methods:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000251 f = self.open(TESTFN, 'rb')
Georg Brandla18af4e2007-04-21 15:47:16 +0000252 if next(f) != filler:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000253 self.fail, "Broken testfile"
254 meth = getattr(f, methodname)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000255 meth(*args) # This simply shouldn't fail
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000256 f.close()
257
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000258 # Test to see if harmless (by accident) mixing of read* and
259 # iteration still works. This depends on the size of the internal
260 # iteration buffer (currently 8192,) but we can test it in a
261 # flexible manner. Each line in the bag o' ham is 4 bytes
262 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
263 # exactly on the buffer boundary for any power-of-2 buffersize
264 # between 4 and 16384 (inclusive).
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000265 f = self.open(TESTFN, 'rb')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000266 for i in range(nchunks):
Georg Brandla18af4e2007-04-21 15:47:16 +0000267 next(f)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000268 testline = testlines.pop(0)
269 try:
270 line = f.readline()
271 except ValueError:
272 self.fail("readline() after next() with supposedly empty "
273 "iteration-buffer failed anyway")
274 if line != testline:
275 self.fail("readline() after next() with empty buffer "
276 "failed. Got %r, expected %r" % (line, testline))
277 testline = testlines.pop(0)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000278 buf = array("b", b"\x00" * len(testline))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000279 try:
280 f.readinto(buf)
281 except ValueError:
282 self.fail("readinto() after next() with supposedly empty "
283 "iteration-buffer failed anyway")
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000284 line = buf.tobytes()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000285 if line != testline:
286 self.fail("readinto() after next() with empty buffer "
287 "failed. Got %r, expected %r" % (line, testline))
288
289 testline = testlines.pop(0)
290 try:
291 line = f.read(len(testline))
292 except ValueError:
293 self.fail("read() after next() with supposedly empty "
294 "iteration-buffer failed anyway")
295 if line != testline:
296 self.fail("read() after next() with empty buffer "
297 "failed. Got %r, expected %r" % (line, testline))
298 try:
299 lines = f.readlines()
300 except ValueError:
301 self.fail("readlines() after next() with supposedly empty "
302 "iteration-buffer failed anyway")
303 if lines != testlines:
304 self.fail("readlines() after next() with empty buffer "
305 "failed. Got %r, expected %r" % (line, testline))
Antoine Pitroua6e95022010-10-30 14:22:43 +0000306 f.close()
307
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000308 # Reading after iteration hit EOF shouldn't hurt either
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000309 f = self.open(TESTFN, 'rb')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000310 try:
311 for line in f:
312 pass
313 try:
314 f.readline()
315 f.readinto(buf)
316 f.read()
317 f.readlines()
318 except ValueError:
319 self.fail("read* failed after next() consumed file")
320 finally:
321 f.close()
322 finally:
323 os.unlink(TESTFN)
324
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000325class COtherFileTests(OtherFileTests):
326 open = io.open
327
328class PyOtherFileTests(OtherFileTests):
329 open = staticmethod(pyio.open)
330
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000331
332def test_main():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000333 # Historically, these tests have been sloppy about removing TESTFN.
334 # So get rid of it no matter what.
335 try:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000336 run_unittest(CAutoFileTests, PyAutoFileTests,
337 COtherFileTests, PyOtherFileTests)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000338 finally:
339 if os.path.exists(TESTFN):
340 os.unlink(TESTFN)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000341
342if __name__ == '__main__':
343 test_main()