blob: 95e9b3e251fc0ed82ec126ee81a4e797acf6e551 [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 # verify the others aren't
38 for attr in 'name', 'mode', 'closed':
39 self.assertRaises((AttributeError, TypeError), setattr, f, attr, 'oops')
40
41 def testReadinto(self):
42 # verify readinto
43 self.f.write('12')
44 self.f.close()
45 a = array('c', 'x'*10)
46 self.f = open(TESTFN, 'rb')
47 n = self.f.readinto(a)
48 self.assertEquals('12', a.tostring()[:n])
49
50 def testReadinto_text(self):
51 # verify readinto refuses text files
52 a = array('c', 'x'*10)
53 self.f.close()
54 self.f = open(TESTFN, 'r')
55 self.assertRaises(TypeError, self.f.readinto, a)
56
57 def testWritelinesUserList(self):
58 # verify writelines with instance sequence
59 l = UserList(['1', '2'])
60 self.f.writelines(l)
61 self.f.close()
62 self.f = open(TESTFN, 'rb')
63 buf = self.f.read()
64 self.assertEquals(buf, '12')
65
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
83 def testRepr(self):
84 # verify repr works
85 self.assert_(repr(self.f).startswith("<open file '" + TESTFN))
86
87 def testErrors(self):
88 f = self.f
89 self.assertEquals(f.name, TESTFN)
90 self.assert_(not f.isatty())
91 self.assert_(not f.closed)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000092
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000093 self.assertRaises(TypeError, f.readinto, "")
94 f.close()
95 self.assert_(f.closed)
96
97 def testMethods(self):
Georg Brandla18af4e2007-04-21 15:47:16 +000098 methods = ['fileno', 'flush', 'isatty', '__next__', 'read', 'readinto',
Thomas Wouters0e3f5912006-08-11 14:57:12 +000099 'readline', 'readlines', 'seek', 'tell', 'truncate',
100 'write', '__iter__']
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000101 if sys.platform.startswith('atheos'):
102 methods.remove('truncate')
103
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000104 # __exit__ should close the file
105 self.f.__exit__(None, None, None)
106 self.assert_(self.f.closed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000107
108 for methodname in methods:
109 method = getattr(self.f, methodname)
110 # should raise on closed file
111 self.assertRaises(ValueError, method)
112 self.assertRaises(ValueError, self.f.writelines, [])
113
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000114 # file is closed, __exit__ shouldn't do anything
115 self.assertEquals(self.f.__exit__(None, None, None), None)
116 # it must also return None if an exception was given
117 try:
118 1/0
119 except:
120 self.assertEquals(self.f.__exit__(*sys.exc_info()), None)
121
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000122
123class OtherFileTests(unittest.TestCase):
124
125 def testModeStrings(self):
126 # check invalid mode strings
127 for mode in ("", "aU", "wU+"):
128 try:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000129 f = open(TESTFN, mode)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000130 except ValueError:
131 pass
132 else:
133 f.close()
134 self.fail('%r is an invalid file mode' % mode)
135
136 def testStdin(self):
137 # This causes the interpreter to exit on OSF1 v5.1.
138 if sys.platform != 'osf1V5':
139 self.assertRaises(IOError, sys.stdin.seek, -1)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000140 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000141 print((
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000142 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000143 ' Test manually.'), file=sys.__stdout__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000144 self.assertRaises(IOError, sys.stdin.truncate)
145
146 def testUnicodeOpen(self):
147 # verify repr works for unicode too
Guido van Rossumef87d6e2007-05-02 19:09:54 +0000148 f = open(str(TESTFN), "w")
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000149 self.assert_(repr(f).startswith("<open file u'" + TESTFN))
Thomas Woutersc45251a2006-02-12 11:53:32 +0000150 f.close()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000151 os.unlink(TESTFN)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000152
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000153 def testBadModeArgument(self):
154 # verify that we get a sensible error message for bad mode argument
155 bad_mode = "qwerty"
Tim Peterscffcfed2006-02-14 17:41:18 +0000156 try:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000157 f = open(TESTFN, bad_mode)
Guido van Rossumb940e112007-01-10 16:19:56 +0000158 except ValueError as msg:
Brett Cannonca477b22007-03-21 22:26:20 +0000159 if msg.args[0] != 0:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000160 s = str(msg)
161 if s.find(TESTFN) != -1 or s.find(bad_mode) == -1:
162 self.fail("bad error message for invalid mode: %s" % s)
163 # if msg[0] == 0, we're probably on Windows where there may be
164 # no obvious way to discover why open() failed.
165 else:
166 f.close()
167 self.fail("no error for invalid mode: %s" % bad_mode)
168
169 def testSetBufferSize(self):
170 # make sure that explicitly setting the buffer size doesn't cause
171 # misbehaviour especially with repeated close() calls
172 for s in (-1, 0, 1, 512):
173 try:
174 f = open(TESTFN, 'w', s)
175 f.write(str(s))
176 f.close()
177 f.close()
178 f = open(TESTFN, 'r', s)
179 d = int(f.read())
180 f.close()
181 f.close()
Guido van Rossumb940e112007-01-10 16:19:56 +0000182 except IOError as msg:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000183 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
184 self.assertEquals(d, s)
185
186 def testTruncateOnWindows(self):
187 os.unlink(TESTFN)
188
189 def bug801631():
190 # SF bug <http://www.python.org/sf/801631>
191 # "file.truncate fault on windows"
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000192 f = open(TESTFN, 'wb')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000193 f.write('12345678901') # 11 bytes
194 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)
198 if data != '12345':
199 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)
211
212 try:
213 bug801631()
214 finally:
215 os.unlink(TESTFN)
216
217 def testIteration(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000218 # Test the complex interaction when mixing file-iteration and the
219 # various read* methods. Ostensibly, the mixture could just be tested
220 # to work when it should work according to the Python language,
221 # instead of fail when it should fail according to the current CPython
222 # implementation. People don't always program Python the way they
223 # should, though, and the implemenation might change in subtle ways,
224 # so we explicitly test for errors, too; the test will just have to
225 # be updated when the implementation changes.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000226 dataoffset = 16384
227 filler = "ham\n"
228 assert not dataoffset % len(filler), \
229 "dataoffset must be multiple of len(filler)"
230 nchunks = dataoffset // len(filler)
231 testlines = [
232 "spam, spam and eggs\n",
233 "eggs, spam, ham and spam\n",
234 "saussages, spam, spam and eggs\n",
235 "spam, ham, spam and eggs\n",
236 "spam, spam, spam, spam, spam, ham, spam\n",
237 "wonderful spaaaaaam.\n"
238 ]
239 methods = [("readline", ()), ("read", ()), ("readlines", ()),
240 ("readinto", (array("c", " "*100),))]
241
242 try:
243 # Prepare the testfile
244 bag = open(TESTFN, "wb")
245 bag.write(filler * nchunks)
246 bag.writelines(testlines)
247 bag.close()
248 # Test for appropriate errors mixing read* and iteration
249 for methodname, args in methods:
250 f = open(TESTFN, 'rb')
Georg Brandla18af4e2007-04-21 15:47:16 +0000251 if next(f) != filler:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000252 self.fail, "Broken testfile"
253 meth = getattr(f, methodname)
254 try:
255 meth(*args)
256 except ValueError:
257 pass
258 else:
259 self.fail("%s%r after next() didn't raise ValueError" %
260 (methodname, args))
261 f.close()
262
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000263 # Test to see if harmless (by accident) mixing of read* and
264 # iteration still works. This depends on the size of the internal
265 # iteration buffer (currently 8192,) but we can test it in a
266 # flexible manner. Each line in the bag o' ham is 4 bytes
267 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
268 # exactly on the buffer boundary for any power-of-2 buffersize
269 # between 4 and 16384 (inclusive).
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000270 f = open(TESTFN, 'rb')
271 for i in range(nchunks):
Georg Brandla18af4e2007-04-21 15:47:16 +0000272 next(f)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000273 testline = testlines.pop(0)
274 try:
275 line = f.readline()
276 except ValueError:
277 self.fail("readline() after next() with supposedly empty "
278 "iteration-buffer failed anyway")
279 if line != testline:
280 self.fail("readline() after next() with empty buffer "
281 "failed. Got %r, expected %r" % (line, testline))
282 testline = testlines.pop(0)
283 buf = array("c", "\x00" * len(testline))
284 try:
285 f.readinto(buf)
286 except ValueError:
287 self.fail("readinto() after next() with supposedly empty "
288 "iteration-buffer failed anyway")
289 line = buf.tostring()
290 if line != testline:
291 self.fail("readinto() after next() with empty buffer "
292 "failed. Got %r, expected %r" % (line, testline))
293
294 testline = testlines.pop(0)
295 try:
296 line = f.read(len(testline))
297 except ValueError:
298 self.fail("read() after next() with supposedly empty "
299 "iteration-buffer failed anyway")
300 if line != testline:
301 self.fail("read() after next() with empty buffer "
302 "failed. Got %r, expected %r" % (line, testline))
303 try:
304 lines = f.readlines()
305 except ValueError:
306 self.fail("readlines() after next() with supposedly empty "
307 "iteration-buffer failed anyway")
308 if lines != testlines:
309 self.fail("readlines() after next() with empty buffer "
310 "failed. Got %r, expected %r" % (line, testline))
311 # Reading after iteration hit EOF shouldn't hurt either
312 f = open(TESTFN, 'rb')
313 try:
314 for line in f:
315 pass
316 try:
317 f.readline()
318 f.readinto(buf)
319 f.read()
320 f.readlines()
321 except ValueError:
322 self.fail("read* failed after next() consumed file")
323 finally:
324 f.close()
325 finally:
326 os.unlink(TESTFN)
327
328
329def test_main():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000330 # Historically, these tests have been sloppy about removing TESTFN.
331 # So get rid of it no matter what.
332 try:
333 run_unittest(AutoFileTests, OtherFileTests)
334 finally:
335 if os.path.exists(TESTFN):
336 os.unlink(TESTFN)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000337
338if __name__ == '__main__':
339 test_main()