blob: 7a68b2f7203a1f7fd46983e44e70d2bb199df8e8 [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 Petersonee8712c2008-05-20 21:35:26 +00007from test.support import TESTFN, findfile, run_unittest
Raymond Hettinger53dbe392008-02-12 20:03:09 +00008from collections import UserList
Marc-André Lemburgfa44d792000-08-25 22:37:31 +00009
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000010class AutoFileTests(unittest.TestCase):
11 # file tests for which a test file is automatically set up
Raymond Hettingercb87bc82004-05-31 00:35:52 +000012
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000013 def setUp(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000014 self.f = open(TESTFN, 'wb')
Tim Peters015dd822003-05-04 04:16:52 +000015
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000016 def tearDown(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000017 if self.f:
18 self.f.close()
19 os.remove(TESTFN)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000020
21 def testWeakRefs(self):
22 # verify weak references
23 p = proxy(self.f)
Guido van Rossume22905a2007-08-27 23:09:25 +000024 p.write(b'teststring')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000025 self.assertEquals(self.f.tell(), p.tell())
26 self.f.close()
27 self.f = None
28 self.assertRaises(ReferenceError, getattr, p, 'tell')
29
30 def testAttributes(self):
31 # verify expected attributes exist
32 f = self.f
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000033 f.name # merely shouldn't blow up
34 f.mode # ditto
35 f.closed # ditto
36
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000037 def testReadinto(self):
38 # verify readinto
Guido van Rossume22905a2007-08-27 23:09:25 +000039 self.f.write(b'12')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000040 self.f.close()
Guido van Rossum7165cb12007-07-10 06:54:34 +000041 a = array('b', b'x'*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000042 self.f = open(TESTFN, 'rb')
43 n = self.f.readinto(a)
Guido van Rossum7165cb12007-07-10 06:54:34 +000044 self.assertEquals(b'12', a.tostring()[:n])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000045
46 def testReadinto_text(self):
47 # verify readinto refuses text files
Guido van Rossum7165cb12007-07-10 06:54:34 +000048 a = array('b', b'x'*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000049 self.f.close()
50 self.f = open(TESTFN, 'r')
Guido van Rossum7165cb12007-07-10 06:54:34 +000051 if hasattr(self.f, "readinto"):
52 self.assertRaises(TypeError, self.f.readinto, a)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000053
54 def testWritelinesUserList(self):
55 # verify writelines with instance sequence
Guido van Rossum7165cb12007-07-10 06:54:34 +000056 l = UserList([b'1', b'2'])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000057 self.f.writelines(l)
58 self.f.close()
59 self.f = open(TESTFN, 'rb')
60 buf = self.f.read()
Guido van Rossum7165cb12007-07-10 06:54:34 +000061 self.assertEquals(buf, b'12')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000062
63 def testWritelinesIntegers(self):
64 # verify writelines with integers
65 self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
66
67 def testWritelinesIntegersUserList(self):
68 # verify writelines with integers in UserList
69 l = UserList([1,2,3])
70 self.assertRaises(TypeError, self.f.writelines, l)
71
72 def testWritelinesNonString(self):
73 # verify writelines with non-string object
Thomas Wouters0e3f5912006-08-11 14:57:12 +000074 class NonString:
75 pass
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000076
Thomas Wouters0e3f5912006-08-11 14:57:12 +000077 self.assertRaises(TypeError, self.f.writelines,
78 [NonString(), NonString()])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000079
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000080 def testErrors(self):
81 f = self.f
82 self.assertEquals(f.name, TESTFN)
83 self.assert_(not f.isatty())
84 self.assert_(not f.closed)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000085
Guido van Rossum7165cb12007-07-10 06:54:34 +000086 if hasattr(f, "readinto"):
87 self.assertRaises((IOError, TypeError), f.readinto, "")
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000088 f.close()
89 self.assert_(f.closed)
90
91 def testMethods(self):
Guido van Rossum4b5386f2007-07-10 09:12:49 +000092 methods = [('fileno', ()),
93 ('flush', ()),
94 ('isatty', ()),
95 ('__next__', ()),
96 ('read', ()),
97 ('write', (b"",)),
98 ('readline', ()),
99 ('readlines', ()),
100 ('seek', (0,)),
101 ('tell', ()),
102 ('write', (b"",)),
103 ('writelines', ([],)),
104 ('__iter__', ()),
105 ]
106 if not sys.platform.startswith('atheos'):
107 methods.append(('truncate', ()))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000108
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000109 # __exit__ should close the file
110 self.f.__exit__(None, None, None)
111 self.assert_(self.f.closed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000112
Guido van Rossum4b5386f2007-07-10 09:12:49 +0000113 for methodname, args in methods:
114 method = getattr(self.f, methodname)
115 # should raise on closed file
116 self.assertRaises(ValueError, method, *args)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000117
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000118 # file is closed, __exit__ shouldn't do anything
119 self.assertEquals(self.f.__exit__(None, None, None), None)
120 # it must also return None if an exception was given
121 try:
122 1/0
123 except:
124 self.assertEquals(self.f.__exit__(*sys.exc_info()), None)
125
Skip Montanaro80072cb2008-12-23 03:51:14 +0000126 def testReadWhenWriting(self):
127 self.assertRaises(IOError, self.f.read)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000128
129class OtherFileTests(unittest.TestCase):
130
131 def testModeStrings(self):
132 # check invalid mode strings
133 for mode in ("", "aU", "wU+"):
134 try:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000135 f = open(TESTFN, mode)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000136 except ValueError:
137 pass
138 else:
139 f.close()
140 self.fail('%r is an invalid file mode' % mode)
141
142 def testStdin(self):
143 # This causes the interpreter to exit on OSF1 v5.1.
144 if sys.platform != 'osf1V5':
Guido van Rossum535a5ef2007-07-10 20:59:22 +0000145 self.assertRaises((IOError, ValueError), sys.stdin.seek, -1)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000146 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000147 print((
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000148 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000149 ' Test manually.'), file=sys.__stdout__)
Guido van Rossum535a5ef2007-07-10 20:59:22 +0000150 self.assertRaises((IOError, ValueError), sys.stdin.truncate)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000151
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000152 def testBadModeArgument(self):
153 # verify that we get a sensible error message for bad mode argument
154 bad_mode = "qwerty"
Tim Peterscffcfed2006-02-14 17:41:18 +0000155 try:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000156 f = open(TESTFN, bad_mode)
Guido van Rossumb940e112007-01-10 16:19:56 +0000157 except ValueError as msg:
Brett Cannonca477b22007-03-21 22:26:20 +0000158 if msg.args[0] != 0:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000159 s = str(msg)
160 if s.find(TESTFN) != -1 or s.find(bad_mode) == -1:
161 self.fail("bad error message for invalid mode: %s" % s)
Georg Brandl50da60c2008-01-06 21:38:54 +0000162 # if msg.args[0] == 0, we're probably on Windows where there may be
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000163 # no obvious way to discover why open() failed.
164 else:
165 f.close()
166 self.fail("no error for invalid mode: %s" % bad_mode)
167
168 def testSetBufferSize(self):
169 # make sure that explicitly setting the buffer size doesn't cause
170 # misbehaviour especially with repeated close() calls
171 for s in (-1, 0, 1, 512):
172 try:
Guido van Rossum7165cb12007-07-10 06:54:34 +0000173 f = open(TESTFN, 'wb', s)
174 f.write(str(s).encode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000175 f.close()
176 f.close()
Guido van Rossum7165cb12007-07-10 06:54:34 +0000177 f = open(TESTFN, 'rb', s)
178 d = int(f.read().decode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000179 f.close()
180 f.close()
Guido van Rossumb940e112007-01-10 16:19:56 +0000181 except IOError as msg:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000182 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
183 self.assertEquals(d, s)
184
185 def testTruncateOnWindows(self):
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000186 # SF bug <http://www.python.org/sf/801631>
187 # "file.truncate fault on windows"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000188
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000189 os.unlink(TESTFN)
190 f = open(TESTFN, 'wb')
191
192 try:
Guido van Rossum7165cb12007-07-10 06:54:34 +0000193 f.write(b'12345678901') # 11 bytes
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000194 f.close()
195
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000196 f = open(TESTFN,'rb+')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000197 data = f.read(5)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000198 if data != b'12345':
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000199 self.fail("Read on file opened for update failed %r" % data)
200 if f.tell() != 5:
201 self.fail("File pos after read wrong %d" % f.tell())
202
203 f.truncate()
204 if f.tell() != 5:
205 self.fail("File pos after ftruncate wrong %d" % f.tell())
206
207 f.close()
208 size = os.path.getsize(TESTFN)
209 if size != 5:
210 self.fail("File size after ftruncate wrong %d" % size)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000211 finally:
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000212 f.close()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000213 os.unlink(TESTFN)
214
215 def testIteration(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000216 # Test the complex interaction when mixing file-iteration and the
Guido van Rossum7165cb12007-07-10 06:54:34 +0000217 # various read* methods.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000218 dataoffset = 16384
Guido van Rossume22905a2007-08-27 23:09:25 +0000219 filler = b"ham\n"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000220 assert not dataoffset % len(filler), \
221 "dataoffset must be multiple of len(filler)"
222 nchunks = dataoffset // len(filler)
223 testlines = [
Guido van Rossum7165cb12007-07-10 06:54:34 +0000224 b"spam, spam and eggs\n",
225 b"eggs, spam, ham and spam\n",
226 b"saussages, spam, spam and eggs\n",
227 b"spam, ham, spam and eggs\n",
228 b"spam, spam, spam, spam, spam, ham, spam\n",
229 b"wonderful spaaaaaam.\n"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000230 ]
231 methods = [("readline", ()), ("read", ()), ("readlines", ()),
Guido van Rossum7165cb12007-07-10 06:54:34 +0000232 ("readinto", (array("b", b" "*100),))]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000233
234 try:
235 # Prepare the testfile
236 bag = open(TESTFN, "wb")
237 bag.write(filler * nchunks)
238 bag.writelines(testlines)
239 bag.close()
240 # Test for appropriate errors mixing read* and iteration
241 for methodname, args in methods:
242 f = open(TESTFN, 'rb')
Georg Brandla18af4e2007-04-21 15:47:16 +0000243 if next(f) != filler:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000244 self.fail, "Broken testfile"
245 meth = getattr(f, methodname)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000246 meth(*args) # This simply shouldn't fail
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000247 f.close()
248
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000249 # Test to see if harmless (by accident) mixing of read* and
250 # iteration still works. This depends on the size of the internal
251 # iteration buffer (currently 8192,) but we can test it in a
252 # flexible manner. Each line in the bag o' ham is 4 bytes
253 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
254 # exactly on the buffer boundary for any power-of-2 buffersize
255 # between 4 and 16384 (inclusive).
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000256 f = open(TESTFN, 'rb')
257 for i in range(nchunks):
Georg Brandla18af4e2007-04-21 15:47:16 +0000258 next(f)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000259 testline = testlines.pop(0)
260 try:
261 line = f.readline()
262 except ValueError:
263 self.fail("readline() after next() with supposedly empty "
264 "iteration-buffer failed anyway")
265 if line != testline:
266 self.fail("readline() after next() with empty buffer "
267 "failed. Got %r, expected %r" % (line, testline))
268 testline = testlines.pop(0)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000269 buf = array("b", b"\x00" * len(testline))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000270 try:
271 f.readinto(buf)
272 except ValueError:
273 self.fail("readinto() after next() with supposedly empty "
274 "iteration-buffer failed anyway")
275 line = buf.tostring()
276 if line != testline:
277 self.fail("readinto() after next() with empty buffer "
278 "failed. Got %r, expected %r" % (line, testline))
279
280 testline = testlines.pop(0)
281 try:
282 line = f.read(len(testline))
283 except ValueError:
284 self.fail("read() after next() with supposedly empty "
285 "iteration-buffer failed anyway")
286 if line != testline:
287 self.fail("read() after next() with empty buffer "
288 "failed. Got %r, expected %r" % (line, testline))
289 try:
290 lines = f.readlines()
291 except ValueError:
292 self.fail("readlines() after next() with supposedly empty "
293 "iteration-buffer failed anyway")
294 if lines != testlines:
295 self.fail("readlines() after next() with empty buffer "
296 "failed. Got %r, expected %r" % (line, testline))
297 # Reading after iteration hit EOF shouldn't hurt either
298 f = open(TESTFN, 'rb')
299 try:
300 for line in f:
301 pass
302 try:
303 f.readline()
304 f.readinto(buf)
305 f.read()
306 f.readlines()
307 except ValueError:
308 self.fail("read* failed after next() consumed file")
309 finally:
310 f.close()
311 finally:
312 os.unlink(TESTFN)
313
314
315def test_main():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000316 # Historically, these tests have been sloppy about removing TESTFN.
317 # So get rid of it no matter what.
318 try:
319 run_unittest(AutoFileTests, OtherFileTests)
320 finally:
321 if os.path.exists(TESTFN):
322 os.unlink(TESTFN)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000323
324if __name__ == '__main__':
325 test_main()