blob: bd2d7c04932faa1012ed3614fe4ea42346ab9b58 [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
Benjamin Petersonee8712c2008-05-20 21:35:26 +000010from test.support import TESTFN, findfile, 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')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000028 self.assertEquals(self.f.tell(), p.tell())
29 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)
Guido van Rossum7165cb12007-07-10 06:54:34 +000047 self.assertEquals(b'12', a.tostring()[: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()
Guido van Rossum7165cb12007-07-10 06:54:34 +000064 self.assertEquals(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
85 self.assertEquals(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 ]
109 if not sys.platform.startswith('atheos'):
110 methods.append(('truncate', ()))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000111
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000112 # __exit__ should close the file
113 self.f.__exit__(None, None, None)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000114 self.assertTrue(self.f.closed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000115
Guido van Rossum4b5386f2007-07-10 09:12:49 +0000116 for methodname, args in methods:
117 method = getattr(self.f, methodname)
118 # should raise on closed file
119 self.assertRaises(ValueError, method, *args)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000120
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000121 # file is closed, __exit__ shouldn't do anything
122 self.assertEquals(self.f.__exit__(None, None, None), None)
123 # it must also return None if an exception was given
124 try:
125 1/0
126 except:
127 self.assertEquals(self.f.__exit__(*sys.exc_info()), None)
128
Skip Montanaro80072cb2008-12-23 03:51:14 +0000129 def testReadWhenWriting(self):
130 self.assertRaises(IOError, self.f.read)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000131
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000132class CAutoFileTests(AutoFileTests):
133 open = io.open
134
135class PyAutoFileTests(AutoFileTests):
136 open = staticmethod(pyio.open)
137
138
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000139class OtherFileTests(unittest.TestCase):
140
141 def testModeStrings(self):
142 # check invalid mode strings
143 for mode in ("", "aU", "wU+"):
144 try:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000145 f = self.open(TESTFN, mode)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000146 except ValueError:
147 pass
148 else:
149 f.close()
150 self.fail('%r is an invalid file mode' % mode)
151
152 def testStdin(self):
153 # This causes the interpreter to exit on OSF1 v5.1.
154 if sys.platform != 'osf1V5':
Guido van Rossum535a5ef2007-07-10 20:59:22 +0000155 self.assertRaises((IOError, ValueError), sys.stdin.seek, -1)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000156 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000157 print((
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000158 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000159 ' Test manually.'), file=sys.__stdout__)
Guido van Rossum535a5ef2007-07-10 20:59:22 +0000160 self.assertRaises((IOError, ValueError), sys.stdin.truncate)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000161
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000162 def testBadModeArgument(self):
163 # verify that we get a sensible error message for bad mode argument
164 bad_mode = "qwerty"
Tim Peterscffcfed2006-02-14 17:41:18 +0000165 try:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000166 f = self.open(TESTFN, bad_mode)
Guido van Rossumb940e112007-01-10 16:19:56 +0000167 except ValueError as msg:
Brett Cannonca477b22007-03-21 22:26:20 +0000168 if msg.args[0] != 0:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000169 s = str(msg)
170 if s.find(TESTFN) != -1 or s.find(bad_mode) == -1:
171 self.fail("bad error message for invalid mode: %s" % s)
Georg Brandl50da60c2008-01-06 21:38:54 +0000172 # if msg.args[0] == 0, we're probably on Windows where there may be
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000173 # no obvious way to discover why open() failed.
174 else:
175 f.close()
176 self.fail("no error for invalid mode: %s" % bad_mode)
177
178 def testSetBufferSize(self):
179 # make sure that explicitly setting the buffer size doesn't cause
180 # misbehaviour especially with repeated close() calls
181 for s in (-1, 0, 1, 512):
182 try:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000183 f = self.open(TESTFN, 'wb', s)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000184 f.write(str(s).encode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000185 f.close()
186 f.close()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000187 f = self.open(TESTFN, 'rb', s)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000188 d = int(f.read().decode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000189 f.close()
190 f.close()
Guido van Rossumb940e112007-01-10 16:19:56 +0000191 except IOError as msg:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000192 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
193 self.assertEquals(d, s)
194
195 def testTruncateOnWindows(self):
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000196 # SF bug <http://www.python.org/sf/801631>
197 # "file.truncate fault on windows"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000198
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000199 os.unlink(TESTFN)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000200 f = self.open(TESTFN, 'wb')
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000201
202 try:
Guido van Rossum7165cb12007-07-10 06:54:34 +0000203 f.write(b'12345678901') # 11 bytes
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000204 f.close()
205
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000206 f = self.open(TESTFN,'rb+')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000207 data = f.read(5)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000208 if data != b'12345':
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000209 self.fail("Read on file opened for update failed %r" % data)
210 if f.tell() != 5:
211 self.fail("File pos after read wrong %d" % f.tell())
212
213 f.truncate()
214 if f.tell() != 5:
215 self.fail("File pos after ftruncate wrong %d" % f.tell())
216
217 f.close()
218 size = os.path.getsize(TESTFN)
219 if size != 5:
220 self.fail("File size after ftruncate wrong %d" % size)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000221 finally:
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000222 f.close()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000223 os.unlink(TESTFN)
224
225 def testIteration(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000226 # Test the complex interaction when mixing file-iteration and the
Guido van Rossum7165cb12007-07-10 06:54:34 +0000227 # various read* methods.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000228 dataoffset = 16384
Guido van Rossume22905a2007-08-27 23:09:25 +0000229 filler = b"ham\n"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000230 assert not dataoffset % len(filler), \
231 "dataoffset must be multiple of len(filler)"
232 nchunks = dataoffset // len(filler)
233 testlines = [
Guido van Rossum7165cb12007-07-10 06:54:34 +0000234 b"spam, spam and eggs\n",
235 b"eggs, spam, ham and spam\n",
236 b"saussages, spam, spam and eggs\n",
237 b"spam, ham, spam and eggs\n",
238 b"spam, spam, spam, spam, spam, ham, spam\n",
239 b"wonderful spaaaaaam.\n"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000240 ]
241 methods = [("readline", ()), ("read", ()), ("readlines", ()),
Guido van Rossum7165cb12007-07-10 06:54:34 +0000242 ("readinto", (array("b", b" "*100),))]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000243
244 try:
245 # Prepare the testfile
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000246 bag = self.open(TESTFN, "wb")
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000247 bag.write(filler * nchunks)
248 bag.writelines(testlines)
249 bag.close()
250 # Test for appropriate errors mixing read* and iteration
251 for methodname, args in methods:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000252 f = self.open(TESTFN, 'rb')
Georg Brandla18af4e2007-04-21 15:47:16 +0000253 if next(f) != filler:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000254 self.fail, "Broken testfile"
255 meth = getattr(f, methodname)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000256 meth(*args) # This simply shouldn't fail
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000257 f.close()
258
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000259 # Test to see if harmless (by accident) mixing of read* and
260 # iteration still works. This depends on the size of the internal
261 # iteration buffer (currently 8192,) but we can test it in a
262 # flexible manner. Each line in the bag o' ham is 4 bytes
263 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
264 # exactly on the buffer boundary for any power-of-2 buffersize
265 # between 4 and 16384 (inclusive).
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000266 f = self.open(TESTFN, 'rb')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000267 for i in range(nchunks):
Georg Brandla18af4e2007-04-21 15:47:16 +0000268 next(f)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000269 testline = testlines.pop(0)
270 try:
271 line = f.readline()
272 except ValueError:
273 self.fail("readline() after next() with supposedly empty "
274 "iteration-buffer failed anyway")
275 if line != testline:
276 self.fail("readline() after next() with empty buffer "
277 "failed. Got %r, expected %r" % (line, testline))
278 testline = testlines.pop(0)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000279 buf = array("b", b"\x00" * len(testline))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000280 try:
281 f.readinto(buf)
282 except ValueError:
283 self.fail("readinto() after next() with supposedly empty "
284 "iteration-buffer failed anyway")
285 line = buf.tostring()
286 if line != testline:
287 self.fail("readinto() after next() with empty buffer "
288 "failed. Got %r, expected %r" % (line, testline))
289
290 testline = testlines.pop(0)
291 try:
292 line = f.read(len(testline))
293 except ValueError:
294 self.fail("read() after next() with supposedly empty "
295 "iteration-buffer failed anyway")
296 if line != testline:
297 self.fail("read() after next() with empty buffer "
298 "failed. Got %r, expected %r" % (line, testline))
299 try:
300 lines = f.readlines()
301 except ValueError:
302 self.fail("readlines() after next() with supposedly empty "
303 "iteration-buffer failed anyway")
304 if lines != testlines:
305 self.fail("readlines() after next() with empty buffer "
306 "failed. Got %r, expected %r" % (line, testline))
307 # Reading after iteration hit EOF shouldn't hurt either
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000308 f = self.open(TESTFN, 'rb')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000309 try:
310 for line in f:
311 pass
312 try:
313 f.readline()
314 f.readinto(buf)
315 f.read()
316 f.readlines()
317 except ValueError:
318 self.fail("read* failed after next() consumed file")
319 finally:
320 f.close()
321 finally:
322 os.unlink(TESTFN)
323
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000324class COtherFileTests(OtherFileTests):
325 open = io.open
326
327class PyOtherFileTests(OtherFileTests):
328 open = staticmethod(pyio.open)
329
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000330
331def test_main():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000332 # Historically, these tests have been sloppy about removing TESTFN.
333 # So get rid of it no matter what.
334 try:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000335 run_unittest(CAutoFileTests, PyAutoFileTests,
336 COtherFileTests, PyOtherFileTests)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000337 finally:
338 if os.path.exists(TESTFN):
339 os.unlink(TESTFN)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000340
341if __name__ == '__main__':
342 test_main()