blob: 076400015c3366e3514d0f91ab1d373bfa7e8ca1 [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
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00007from test.test_support import TESTFN, findfile, run_unittest
Marc-André Lemburgfa44d792000-08-25 22:37:31 +00008from UserList import UserList
9
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)
24 p.write('teststring')
25 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
39 self.f.write('12')
40 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
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000126
127class OtherFileTests(unittest.TestCase):
128
129 def testModeStrings(self):
130 # check invalid mode strings
131 for mode in ("", "aU", "wU+"):
132 try:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000133 f = open(TESTFN, mode)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000134 except ValueError:
135 pass
136 else:
137 f.close()
138 self.fail('%r is an invalid file mode' % mode)
139
140 def testStdin(self):
141 # This causes the interpreter to exit on OSF1 v5.1.
142 if sys.platform != 'osf1V5':
Guido van Rossum7165cb12007-07-10 06:54:34 +0000143 self.assertRaises(ValueError, sys.stdin.seek, -1)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000144 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000145 print((
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000146 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000147 ' Test manually.'), file=sys.__stdout__)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000148 self.assertRaises(ValueError, sys.stdin.truncate)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000149
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000150 def testBadModeArgument(self):
151 # verify that we get a sensible error message for bad mode argument
152 bad_mode = "qwerty"
Tim Peterscffcfed2006-02-14 17:41:18 +0000153 try:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000154 f = open(TESTFN, bad_mode)
Guido van Rossumb940e112007-01-10 16:19:56 +0000155 except ValueError as msg:
Brett Cannonca477b22007-03-21 22:26:20 +0000156 if msg.args[0] != 0:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000157 s = str(msg)
158 if s.find(TESTFN) != -1 or s.find(bad_mode) == -1:
159 self.fail("bad error message for invalid mode: %s" % s)
160 # if msg[0] == 0, we're probably on Windows where there may be
161 # no obvious way to discover why open() failed.
162 else:
163 f.close()
164 self.fail("no error for invalid mode: %s" % bad_mode)
165
166 def testSetBufferSize(self):
167 # make sure that explicitly setting the buffer size doesn't cause
168 # misbehaviour especially with repeated close() calls
169 for s in (-1, 0, 1, 512):
170 try:
Guido van Rossum7165cb12007-07-10 06:54:34 +0000171 f = open(TESTFN, 'wb', s)
172 f.write(str(s).encode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000173 f.close()
174 f.close()
Guido van Rossum7165cb12007-07-10 06:54:34 +0000175 f = open(TESTFN, 'rb', s)
176 d = int(f.read().decode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000177 f.close()
178 f.close()
Guido van Rossumb940e112007-01-10 16:19:56 +0000179 except IOError as msg:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000180 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
181 self.assertEquals(d, s)
182
183 def testTruncateOnWindows(self):
184 os.unlink(TESTFN)
185
186 def bug801631():
187 # SF bug <http://www.python.org/sf/801631>
188 # "file.truncate fault on windows"
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000189 f = open(TESTFN, 'wb')
Guido van Rossum7165cb12007-07-10 06:54:34 +0000190 f.write(b'12345678901') # 11 bytes
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000191 f.close()
192
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000193 f = open(TESTFN,'rb+')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000194 data = f.read(5)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000195 if data != b'12345':
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000196 self.fail("Read on file opened for update failed %r" % data)
197 if f.tell() != 5:
198 self.fail("File pos after read wrong %d" % f.tell())
199
200 f.truncate()
201 if f.tell() != 5:
202 self.fail("File pos after ftruncate wrong %d" % f.tell())
203
204 f.close()
205 size = os.path.getsize(TESTFN)
206 if size != 5:
207 self.fail("File size after ftruncate wrong %d" % size)
208
209 try:
210 bug801631()
211 finally:
212 os.unlink(TESTFN)
213
214 def testIteration(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000215 # Test the complex interaction when mixing file-iteration and the
Guido van Rossum7165cb12007-07-10 06:54:34 +0000216 # various read* methods.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000217 dataoffset = 16384
218 filler = "ham\n"
219 assert not dataoffset % len(filler), \
220 "dataoffset must be multiple of len(filler)"
221 nchunks = dataoffset // len(filler)
222 testlines = [
Guido van Rossum7165cb12007-07-10 06:54:34 +0000223 b"spam, spam and eggs\n",
224 b"eggs, spam, ham and spam\n",
225 b"saussages, spam, spam and eggs\n",
226 b"spam, ham, spam and eggs\n",
227 b"spam, spam, spam, spam, spam, ham, spam\n",
228 b"wonderful spaaaaaam.\n"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000229 ]
230 methods = [("readline", ()), ("read", ()), ("readlines", ()),
Guido van Rossum7165cb12007-07-10 06:54:34 +0000231 ("readinto", (array("b", b" "*100),))]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000232
233 try:
234 # Prepare the testfile
235 bag = open(TESTFN, "wb")
236 bag.write(filler * nchunks)
237 bag.writelines(testlines)
238 bag.close()
239 # Test for appropriate errors mixing read* and iteration
240 for methodname, args in methods:
241 f = open(TESTFN, 'rb')
Georg Brandla18af4e2007-04-21 15:47:16 +0000242 if next(f) != filler:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000243 self.fail, "Broken testfile"
244 meth = getattr(f, methodname)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000245 meth(*args) # This simply shouldn't fail
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000246 f.close()
247
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000248 # Test to see if harmless (by accident) mixing of read* and
249 # iteration still works. This depends on the size of the internal
250 # iteration buffer (currently 8192,) but we can test it in a
251 # flexible manner. Each line in the bag o' ham is 4 bytes
252 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
253 # exactly on the buffer boundary for any power-of-2 buffersize
254 # between 4 and 16384 (inclusive).
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000255 f = open(TESTFN, 'rb')
256 for i in range(nchunks):
Georg Brandla18af4e2007-04-21 15:47:16 +0000257 next(f)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000258 testline = testlines.pop(0)
259 try:
260 line = f.readline()
261 except ValueError:
262 self.fail("readline() after next() with supposedly empty "
263 "iteration-buffer failed anyway")
264 if line != testline:
265 self.fail("readline() after next() with empty buffer "
266 "failed. Got %r, expected %r" % (line, testline))
267 testline = testlines.pop(0)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000268 buf = array("b", b"\x00" * len(testline))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000269 try:
270 f.readinto(buf)
271 except ValueError:
272 self.fail("readinto() after next() with supposedly empty "
273 "iteration-buffer failed anyway")
274 line = buf.tostring()
275 if line != testline:
276 self.fail("readinto() after next() with empty buffer "
277 "failed. Got %r, expected %r" % (line, testline))
278
279 testline = testlines.pop(0)
280 try:
281 line = f.read(len(testline))
282 except ValueError:
283 self.fail("read() after next() with supposedly empty "
284 "iteration-buffer failed anyway")
285 if line != testline:
286 self.fail("read() after next() with empty buffer "
287 "failed. Got %r, expected %r" % (line, testline))
288 try:
289 lines = f.readlines()
290 except ValueError:
291 self.fail("readlines() after next() with supposedly empty "
292 "iteration-buffer failed anyway")
293 if lines != testlines:
294 self.fail("readlines() after next() with empty buffer "
295 "failed. Got %r, expected %r" % (line, testline))
296 # Reading after iteration hit EOF shouldn't hurt either
297 f = open(TESTFN, 'rb')
298 try:
299 for line in f:
300 pass
301 try:
302 f.readline()
303 f.readinto(buf)
304 f.read()
305 f.readlines()
306 except ValueError:
307 self.fail("read* failed after next() consumed file")
308 finally:
309 f.close()
310 finally:
311 os.unlink(TESTFN)
312
313
314def test_main():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000315 # Historically, these tests have been sloppy about removing TESTFN.
316 # So get rid of it no matter what.
317 try:
318 run_unittest(AutoFileTests, OtherFileTests)
319 finally:
320 if os.path.exists(TESTFN):
321 os.unlink(TESTFN)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000322
323if __name__ == '__main__':
324 test_main()