blob: 4b0c75929de28feb60191a72a9a688d89ab6901a [file] [log] [blame]
Antoine Pitrou19690592009-06-12 20:14:08 +00001from __future__ import print_function
2
Martin v. Löwisf90ae202002-06-11 06:22:31 +00003import sys
Fred Drake2ec80fa2000-10-23 16:59:35 +00004import os
Georg Brandl442b49e2006-06-08 14:50:53 +00005import unittest
Neal Norwitz62f5a9d2002-04-01 00:09:00 +00006from array import array
Raymond Hettingercb87bc82004-05-31 00:35:52 +00007from weakref import proxy
Fred Drake2ec80fa2000-10-23 16:59:35 +00008
Antoine Pitrou19690592009-06-12 20:14:08 +00009import io
10import _pyio as pyio
11
Georg Brandl442b49e2006-06-08 14:50:53 +000012from test.test_support import TESTFN, findfile, run_unittest
Marc-André Lemburgfa44d792000-08-25 22:37:31 +000013from UserList import UserList
14
Georg Brandl442b49e2006-06-08 14:50:53 +000015class AutoFileTests(unittest.TestCase):
16 # file tests for which a test file is automatically set up
Raymond Hettingercb87bc82004-05-31 00:35:52 +000017
Georg Brandl442b49e2006-06-08 14:50:53 +000018 def setUp(self):
Antoine Pitrou19690592009-06-12 20:14:08 +000019 self.f = self.open(TESTFN, 'wb')
Tim Peters015dd822003-05-04 04:16:52 +000020
Georg Brandl442b49e2006-06-08 14:50:53 +000021 def tearDown(self):
Tim Petersdbb82f62006-06-09 03:51:41 +000022 if self.f:
23 self.f.close()
24 os.remove(TESTFN)
Georg Brandl442b49e2006-06-08 14:50:53 +000025
26 def testWeakRefs(self):
27 # verify weak references
28 p = proxy(self.f)
Antoine Pitrou19690592009-06-12 20:14:08 +000029 p.write(b'teststring')
Georg Brandl442b49e2006-06-08 14:50:53 +000030 self.assertEquals(self.f.tell(), p.tell())
31 self.f.close()
32 self.f = None
33 self.assertRaises(ReferenceError, getattr, p, 'tell')
34
35 def testAttributes(self):
36 # verify expected attributes exist
37 f = self.f
Georg Brandl442b49e2006-06-08 14:50:53 +000038 f.name # merely shouldn't blow up
39 f.mode # ditto
40 f.closed # ditto
41
Georg Brandl442b49e2006-06-08 14:50:53 +000042 def testReadinto(self):
43 # verify readinto
Antoine Pitrou19690592009-06-12 20:14:08 +000044 self.f.write(b'12')
Georg Brandl442b49e2006-06-08 14:50:53 +000045 self.f.close()
Antoine Pitrou19690592009-06-12 20:14:08 +000046 a = array('b', b'x'*10)
47 self.f = self.open(TESTFN, 'rb')
Georg Brandl442b49e2006-06-08 14:50:53 +000048 n = self.f.readinto(a)
Antoine Pitrou19690592009-06-12 20:14:08 +000049 self.assertEquals(b'12', a.tostring()[:n])
50
51 def testReadinto_text(self):
52 # verify readinto refuses text files
53 a = array('b', b'x'*10)
54 self.f.close()
55 self.f = self.open(TESTFN, 'r')
56 if hasattr(self.f, "readinto"):
57 self.assertRaises(TypeError, self.f.readinto, a)
Georg Brandl442b49e2006-06-08 14:50:53 +000058
59 def testWritelinesUserList(self):
60 # verify writelines with instance sequence
Antoine Pitrou19690592009-06-12 20:14:08 +000061 l = UserList([b'1', b'2'])
Georg Brandl442b49e2006-06-08 14:50:53 +000062 self.f.writelines(l)
63 self.f.close()
Antoine Pitrou19690592009-06-12 20:14:08 +000064 self.f = self.open(TESTFN, 'rb')
Georg Brandl442b49e2006-06-08 14:50:53 +000065 buf = self.f.read()
Antoine Pitrou19690592009-06-12 20:14:08 +000066 self.assertEquals(buf, b'12')
Georg Brandl442b49e2006-06-08 14:50:53 +000067
68 def testWritelinesIntegers(self):
69 # verify writelines with integers
70 self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
71
72 def testWritelinesIntegersUserList(self):
73 # verify writelines with integers in UserList
74 l = UserList([1,2,3])
75 self.assertRaises(TypeError, self.f.writelines, l)
76
77 def testWritelinesNonString(self):
78 # verify writelines with non-string object
Tim Petersdbb82f62006-06-09 03:51:41 +000079 class NonString:
80 pass
Georg Brandl442b49e2006-06-08 14:50:53 +000081
Tim Petersdbb82f62006-06-09 03:51:41 +000082 self.assertRaises(TypeError, self.f.writelines,
83 [NonString(), NonString()])
Georg Brandl442b49e2006-06-08 14:50:53 +000084
Georg Brandl442b49e2006-06-08 14:50:53 +000085 def testErrors(self):
86 f = self.f
87 self.assertEquals(f.name, TESTFN)
88 self.assert_(not f.isatty())
89 self.assert_(not f.closed)
Tim Peters520d8dd2006-06-09 02:11:02 +000090
Antoine Pitrou19690592009-06-12 20:14:08 +000091 if hasattr(f, "readinto"):
92 self.assertRaises((IOError, TypeError), f.readinto, "")
Georg Brandl442b49e2006-06-08 14:50:53 +000093 f.close()
94 self.assert_(f.closed)
95
96 def testMethods(self):
Antoine Pitrou19690592009-06-12 20:14:08 +000097 methods = [('fileno', ()),
98 ('flush', ()),
99 ('isatty', ()),
100 ('next', ()),
101 ('read', ()),
102 ('write', (b"",)),
103 ('readline', ()),
104 ('readlines', ()),
105 ('seek', (0,)),
106 ('tell', ()),
107 ('write', (b"",)),
108 ('writelines', ([],)),
109 ('__iter__', ()),
110 ]
111 if not sys.platform.startswith('atheos'):
112 methods.append(('truncate', ()))
Georg Brandl442b49e2006-06-08 14:50:53 +0000113
Georg Brandle7ec81f2006-06-09 18:29:52 +0000114 # __exit__ should close the file
115 self.f.__exit__(None, None, None)
116 self.assert_(self.f.closed)
Georg Brandl442b49e2006-06-08 14:50:53 +0000117
Antoine Pitrou19690592009-06-12 20:14:08 +0000118 for methodname, args in methods:
Georg Brandl442b49e2006-06-08 14:50:53 +0000119 method = getattr(self.f, methodname)
120 # should raise on closed file
Antoine Pitrou19690592009-06-12 20:14:08 +0000121 self.assertRaises(ValueError, method, *args)
Georg Brandl442b49e2006-06-08 14:50:53 +0000122
Georg Brandle7ec81f2006-06-09 18:29:52 +0000123 # file is closed, __exit__ shouldn't do anything
124 self.assertEquals(self.f.__exit__(None, None, None), None)
125 # it must also return None if an exception was given
126 try:
127 1/0
128 except:
129 self.assertEquals(self.f.__exit__(*sys.exc_info()), None)
130
Skip Montanarof205c132008-12-23 03:30:15 +0000131 def testReadWhenWriting(self):
132 self.assertRaises(IOError, self.f.read)
Georg Brandl442b49e2006-06-08 14:50:53 +0000133
Antoine Pitrou19690592009-06-12 20:14:08 +0000134class CAutoFileTests(AutoFileTests):
135 open = io.open
Georg Brandl442b49e2006-06-08 14:50:53 +0000136
Antoine Pitrou19690592009-06-12 20:14:08 +0000137class PyAutoFileTests(AutoFileTests):
138 open = staticmethod(pyio.open)
139
140
141class OtherFileTests(unittest.TestCase):
Benjamin Petersonfe231b02008-12-29 17:47:42 +0000142
Georg Brandl442b49e2006-06-08 14:50:53 +0000143 def testModeStrings(self):
144 # check invalid mode strings
145 for mode in ("", "aU", "wU+"):
146 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000147 f = self.open(TESTFN, mode)
Georg Brandl442b49e2006-06-08 14:50:53 +0000148 except ValueError:
149 pass
150 else:
151 f.close()
152 self.fail('%r is an invalid file mode' % mode)
153
154 def testStdin(self):
155 # This causes the interpreter to exit on OSF1 v5.1.
156 if sys.platform != 'osf1V5':
Antoine Pitrou19690592009-06-12 20:14:08 +0000157 self.assertRaises((IOError, ValueError), sys.stdin.seek, -1)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000158 else:
Antoine Pitrou19690592009-06-12 20:14:08 +0000159 print((
Georg Brandl442b49e2006-06-08 14:50:53 +0000160 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
Antoine Pitrou19690592009-06-12 20:14:08 +0000161 ' Test manually.'), file=sys.__stdout__)
162 self.assertRaises((IOError, ValueError), sys.stdin.truncate)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000163
Georg Brandl442b49e2006-06-08 14:50:53 +0000164 def testBadModeArgument(self):
165 # verify that we get a sensible error message for bad mode argument
166 bad_mode = "qwerty"
Tim Peterscffcfed2006-02-14 17:41:18 +0000167 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000168 f = self.open(TESTFN, bad_mode)
169 except ValueError as msg:
170 if msg.args[0] != 0:
Georg Brandl442b49e2006-06-08 14:50:53 +0000171 s = str(msg)
172 if s.find(TESTFN) != -1 or s.find(bad_mode) == -1:
173 self.fail("bad error message for invalid mode: %s" % s)
Antoine Pitrou19690592009-06-12 20:14:08 +0000174 # if msg.args[0] == 0, we're probably on Windows where there may be
Georg Brandl442b49e2006-06-08 14:50:53 +0000175 # no obvious way to discover why open() failed.
176 else:
177 f.close()
178 self.fail("no error for invalid mode: %s" % bad_mode)
179
180 def testSetBufferSize(self):
181 # make sure that explicitly setting the buffer size doesn't cause
182 # misbehaviour especially with repeated close() calls
183 for s in (-1, 0, 1, 512):
184 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000185 f = self.open(TESTFN, 'wb', s)
186 f.write(str(s).encode("ascii"))
Georg Brandl442b49e2006-06-08 14:50:53 +0000187 f.close()
188 f.close()
Antoine Pitrou19690592009-06-12 20:14:08 +0000189 f = self.open(TESTFN, 'rb', s)
190 d = int(f.read().decode("ascii"))
Georg Brandl442b49e2006-06-08 14:50:53 +0000191 f.close()
192 f.close()
Antoine Pitrou19690592009-06-12 20:14:08 +0000193 except IOError as msg:
Georg Brandl442b49e2006-06-08 14:50:53 +0000194 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
195 self.assertEquals(d, s)
196
197 def testTruncateOnWindows(self):
Antoine Pitrou19690592009-06-12 20:14:08 +0000198 # SF bug <http://www.python.org/sf/801631>
199 # "file.truncate fault on windows"
Georg Brandl442b49e2006-06-08 14:50:53 +0000200
Antoine Pitrou19690592009-06-12 20:14:08 +0000201 os.unlink(TESTFN)
202 f = self.open(TESTFN, 'wb')
203
204 try:
205 f.write(b'12345678901') # 11 bytes
Georg Brandl442b49e2006-06-08 14:50:53 +0000206 f.close()
207
Antoine Pitrou19690592009-06-12 20:14:08 +0000208 f = self.open(TESTFN,'rb+')
Georg Brandl442b49e2006-06-08 14:50:53 +0000209 data = f.read(5)
Antoine Pitrou19690592009-06-12 20:14:08 +0000210 if data != b'12345':
Georg Brandl442b49e2006-06-08 14:50:53 +0000211 self.fail("Read on file opened for update failed %r" % data)
212 if f.tell() != 5:
213 self.fail("File pos after read wrong %d" % f.tell())
214
215 f.truncate()
216 if f.tell() != 5:
217 self.fail("File pos after ftruncate wrong %d" % f.tell())
218
219 f.close()
220 size = os.path.getsize(TESTFN)
221 if size != 5:
222 self.fail("File size after ftruncate wrong %d" % size)
Georg Brandl442b49e2006-06-08 14:50:53 +0000223 finally:
Antoine Pitrou19690592009-06-12 20:14:08 +0000224 f.close()
Georg Brandl442b49e2006-06-08 14:50:53 +0000225 os.unlink(TESTFN)
226
227 def testIteration(self):
Tim Petersdbb82f62006-06-09 03:51:41 +0000228 # Test the complex interaction when mixing file-iteration and the
Antoine Pitrou19690592009-06-12 20:14:08 +0000229 # various read* methods.
Georg Brandl442b49e2006-06-08 14:50:53 +0000230 dataoffset = 16384
Antoine Pitrou19690592009-06-12 20:14:08 +0000231 filler = b"ham\n"
Georg Brandl442b49e2006-06-08 14:50:53 +0000232 assert not dataoffset % len(filler), \
233 "dataoffset must be multiple of len(filler)"
234 nchunks = dataoffset // len(filler)
235 testlines = [
Antoine Pitrou19690592009-06-12 20:14:08 +0000236 b"spam, spam and eggs\n",
237 b"eggs, spam, ham and spam\n",
238 b"saussages, spam, spam and eggs\n",
239 b"spam, ham, spam and eggs\n",
240 b"spam, spam, spam, spam, spam, ham, spam\n",
241 b"wonderful spaaaaaam.\n"
Georg Brandl442b49e2006-06-08 14:50:53 +0000242 ]
243 methods = [("readline", ()), ("read", ()), ("readlines", ()),
Antoine Pitrou19690592009-06-12 20:14:08 +0000244 ("readinto", (array("b", b" "*100),))]
Georg Brandl442b49e2006-06-08 14:50:53 +0000245
246 try:
247 # Prepare the testfile
Antoine Pitrou19690592009-06-12 20:14:08 +0000248 bag = self.open(TESTFN, "wb")
Georg Brandl442b49e2006-06-08 14:50:53 +0000249 bag.write(filler * nchunks)
250 bag.writelines(testlines)
251 bag.close()
252 # Test for appropriate errors mixing read* and iteration
253 for methodname, args in methods:
Antoine Pitrou19690592009-06-12 20:14:08 +0000254 f = self.open(TESTFN, 'rb')
255 if next(f) != filler:
Georg Brandl442b49e2006-06-08 14:50:53 +0000256 self.fail, "Broken testfile"
257 meth = getattr(f, methodname)
Antoine Pitrou19690592009-06-12 20:14:08 +0000258 meth(*args) # This simply shouldn't fail
Georg Brandl442b49e2006-06-08 14:50:53 +0000259 f.close()
260
Tim Petersdbb82f62006-06-09 03:51:41 +0000261 # Test to see if harmless (by accident) mixing of read* and
262 # iteration still works. This depends on the size of the internal
263 # iteration buffer (currently 8192,) but we can test it in a
264 # flexible manner. Each line in the bag o' ham is 4 bytes
265 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
266 # exactly on the buffer boundary for any power-of-2 buffersize
267 # between 4 and 16384 (inclusive).
Antoine Pitrou19690592009-06-12 20:14:08 +0000268 f = self.open(TESTFN, 'rb')
Georg Brandl442b49e2006-06-08 14:50:53 +0000269 for i in range(nchunks):
Antoine Pitrou19690592009-06-12 20:14:08 +0000270 next(f)
Georg Brandl442b49e2006-06-08 14:50:53 +0000271 testline = testlines.pop(0)
272 try:
273 line = f.readline()
274 except ValueError:
275 self.fail("readline() after next() with supposedly empty "
276 "iteration-buffer failed anyway")
277 if line != testline:
278 self.fail("readline() after next() with empty buffer "
279 "failed. Got %r, expected %r" % (line, testline))
280 testline = testlines.pop(0)
Antoine Pitrou19690592009-06-12 20:14:08 +0000281 buf = array("b", b"\x00" * len(testline))
Georg Brandl442b49e2006-06-08 14:50:53 +0000282 try:
283 f.readinto(buf)
284 except ValueError:
285 self.fail("readinto() after next() with supposedly empty "
286 "iteration-buffer failed anyway")
287 line = buf.tostring()
288 if line != testline:
289 self.fail("readinto() after next() with empty buffer "
290 "failed. Got %r, expected %r" % (line, testline))
291
292 testline = testlines.pop(0)
293 try:
294 line = f.read(len(testline))
295 except ValueError:
296 self.fail("read() after next() with supposedly empty "
297 "iteration-buffer failed anyway")
298 if line != testline:
299 self.fail("read() after next() with empty buffer "
300 "failed. Got %r, expected %r" % (line, testline))
301 try:
302 lines = f.readlines()
303 except ValueError:
304 self.fail("readlines() after next() with supposedly empty "
305 "iteration-buffer failed anyway")
306 if lines != testlines:
307 self.fail("readlines() after next() with empty buffer "
308 "failed. Got %r, expected %r" % (line, testline))
309 # Reading after iteration hit EOF shouldn't hurt either
Antoine Pitrou19690592009-06-12 20:14:08 +0000310 f = self.open(TESTFN, 'rb')
Georg Brandl442b49e2006-06-08 14:50:53 +0000311 try:
312 for line in f:
313 pass
314 try:
315 f.readline()
316 f.readinto(buf)
317 f.read()
318 f.readlines()
319 except ValueError:
320 self.fail("read* failed after next() consumed file")
321 finally:
322 f.close()
323 finally:
324 os.unlink(TESTFN)
325
Antoine Pitrou19690592009-06-12 20:14:08 +0000326class COtherFileTests(OtherFileTests):
327 open = io.open
Georg Brandlad61bc82008-02-23 15:11:18 +0000328
Antoine Pitrou19690592009-06-12 20:14:08 +0000329class PyOtherFileTests(OtherFileTests):
330 open = staticmethod(pyio.open)
Jeffrey Yasskin2d873bd2008-12-08 18:55:24 +0000331
Gregory P. Smithaa63d0d2008-04-06 23:11:17 +0000332
Georg Brandl442b49e2006-06-08 14:50:53 +0000333def test_main():
Neal Norwitzc9778a82006-06-09 05:54:18 +0000334 # Historically, these tests have been sloppy about removing TESTFN.
335 # So get rid of it no matter what.
Tim Peters0556e9b2006-06-09 04:02:06 +0000336 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000337 run_unittest(CAutoFileTests, PyAutoFileTests,
338 COtherFileTests, PyOtherFileTests)
Tim Peters0556e9b2006-06-09 04:02:06 +0000339 finally:
340 if os.path.exists(TESTFN):
341 os.unlink(TESTFN)
Georg Brandl442b49e2006-06-08 14:50:53 +0000342
343if __name__ == '__main__':
344 test_main()