source: trunk/essentials/dev-lang/python/Lib/test/test_file.py@ 3317

Last change on this file since 3317 was 3225, checked in by bird, 19 years ago

Python 2.5

File size: 11.8 KB
Line 
1import sys
2import os
3import unittest
4from array import array
5from weakref import proxy
6
7from test.test_support import TESTFN, findfile, run_unittest
8from UserList import UserList
9
10class AutoFileTests(unittest.TestCase):
11 # file tests for which a test file is automatically set up
12
13 def setUp(self):
14 self.f = open(TESTFN, 'wb')
15
16 def tearDown(self):
17 if self.f:
18 self.f.close()
19 os.remove(TESTFN)
20
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
33 softspace = f.softspace
34 f.name # merely shouldn't blow up
35 f.mode # ditto
36 f.closed # ditto
37
38 # verify softspace is writable
39 f.softspace = softspace # merely shouldn't blow up
40
41 # verify the others aren't
42 for attr in 'name', 'mode', 'closed':
43 self.assertRaises((AttributeError, TypeError), setattr, f, attr, 'oops')
44
45 def testReadinto(self):
46 # verify readinto
47 self.f.write('12')
48 self.f.close()
49 a = array('c', 'x'*10)
50 self.f = open(TESTFN, 'rb')
51 n = self.f.readinto(a)
52 self.assertEquals('12', a.tostring()[:n])
53
54 def testWritelinesUserList(self):
55 # verify writelines with instance sequence
56 l = UserList(['1', '2'])
57 self.f.writelines(l)
58 self.f.close()
59 self.f = open(TESTFN, 'rb')
60 buf = self.f.read()
61 self.assertEquals(buf, '12')
62
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
74 class NonString:
75 pass
76
77 self.assertRaises(TypeError, self.f.writelines,
78 [NonString(), NonString()])
79
80 def testRepr(self):
81 # verify repr works
82 self.assert_(repr(self.f).startswith("<open file '" + TESTFN))
83
84 def testErrors(self):
85 f = self.f
86 self.assertEquals(f.name, TESTFN)
87 self.assert_(not f.isatty())
88 self.assert_(not f.closed)
89
90 self.assertRaises(TypeError, f.readinto, "")
91 f.close()
92 self.assert_(f.closed)
93
94 def testMethods(self):
95 methods = ['fileno', 'flush', 'isatty', 'next', 'read', 'readinto',
96 'readline', 'readlines', 'seek', 'tell', 'truncate',
97 'write', 'xreadlines', '__iter__']
98 if sys.platform.startswith('atheos'):
99 methods.remove('truncate')
100
101 # __exit__ should close the file
102 self.f.__exit__(None, None, None)
103 self.assert_(self.f.closed)
104
105 for methodname in methods:
106 method = getattr(self.f, methodname)
107 # should raise on closed file
108 self.assertRaises(ValueError, method)
109 self.assertRaises(ValueError, self.f.writelines, [])
110
111 # file is closed, __exit__ shouldn't do anything
112 self.assertEquals(self.f.__exit__(None, None, None), None)
113 # it must also return None if an exception was given
114 try:
115 1/0
116 except:
117 self.assertEquals(self.f.__exit__(*sys.exc_info()), None)
118
119
120class OtherFileTests(unittest.TestCase):
121
122 def testModeStrings(self):
123 # check invalid mode strings
124 for mode in ("", "aU", "wU+"):
125 try:
126 f = open(TESTFN, mode)
127 except ValueError:
128 pass
129 else:
130 f.close()
131 self.fail('%r is an invalid file mode' % mode)
132
133 def testStdin(self):
134 # This causes the interpreter to exit on OSF1 v5.1.
135 if sys.platform != 'osf1V5':
136 self.assertRaises(IOError, sys.stdin.seek, -1)
137 else:
138 print >>sys.__stdout__, (
139 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
140 ' Test manually.')
141 self.assertRaises(IOError, sys.stdin.truncate)
142
143 def testUnicodeOpen(self):
144 # verify repr works for unicode too
145 f = open(unicode(TESTFN), "w")
146 self.assert_(repr(f).startswith("<open file u'" + TESTFN))
147 f.close()
148 os.unlink(TESTFN)
149
150 def testBadModeArgument(self):
151 # verify that we get a sensible error message for bad mode argument
152 bad_mode = "qwerty"
153 try:
154 f = open(TESTFN, bad_mode)
155 except ValueError, msg:
156 if msg[0] != 0:
157 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:
171 f = open(TESTFN, 'w', s)
172 f.write(str(s))
173 f.close()
174 f.close()
175 f = open(TESTFN, 'r', s)
176 d = int(f.read())
177 f.close()
178 f.close()
179 except IOError, msg:
180 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"
189 f = open(TESTFN, 'wb')
190 f.write('12345678901') # 11 bytes
191 f.close()
192
193 f = open(TESTFN,'rb+')
194 data = f.read(5)
195 if data != '12345':
196 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):
215 # Test the complex interaction when mixing file-iteration and the
216 # various read* methods. Ostensibly, the mixture could just be tested
217 # to work when it should work according to the Python language,
218 # instead of fail when it should fail according to the current CPython
219 # implementation. People don't always program Python the way they
220 # should, though, and the implemenation might change in subtle ways,
221 # so we explicitly test for errors, too; the test will just have to
222 # be updated when the implementation changes.
223 dataoffset = 16384
224 filler = "ham\n"
225 assert not dataoffset % len(filler), \
226 "dataoffset must be multiple of len(filler)"
227 nchunks = dataoffset // len(filler)
228 testlines = [
229 "spam, spam and eggs\n",
230 "eggs, spam, ham and spam\n",
231 "saussages, spam, spam and eggs\n",
232 "spam, ham, spam and eggs\n",
233 "spam, spam, spam, spam, spam, ham, spam\n",
234 "wonderful spaaaaaam.\n"
235 ]
236 methods = [("readline", ()), ("read", ()), ("readlines", ()),
237 ("readinto", (array("c", " "*100),))]
238
239 try:
240 # Prepare the testfile
241 bag = open(TESTFN, "w")
242 bag.write(filler * nchunks)
243 bag.writelines(testlines)
244 bag.close()
245 # Test for appropriate errors mixing read* and iteration
246 for methodname, args in methods:
247 f = open(TESTFN)
248 if f.next() != filler:
249 self.fail, "Broken testfile"
250 meth = getattr(f, methodname)
251 try:
252 meth(*args)
253 except ValueError:
254 pass
255 else:
256 self.fail("%s%r after next() didn't raise ValueError" %
257 (methodname, args))
258 f.close()
259
260 # Test to see if harmless (by accident) mixing of read* and
261 # iteration still works. This depends on the size of the internal
262 # iteration buffer (currently 8192,) but we can test it in a
263 # flexible manner. Each line in the bag o' ham is 4 bytes
264 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
265 # exactly on the buffer boundary for any power-of-2 buffersize
266 # between 4 and 16384 (inclusive).
267 f = open(TESTFN)
268 for i in range(nchunks):
269 f.next()
270 testline = testlines.pop(0)
271 try:
272 line = f.readline()
273 except ValueError:
274 self.fail("readline() after next() with supposedly empty "
275 "iteration-buffer failed anyway")
276 if line != testline:
277 self.fail("readline() after next() with empty buffer "
278 "failed. Got %r, expected %r" % (line, testline))
279 testline = testlines.pop(0)
280 buf = array("c", "\x00" * len(testline))
281 try:
282 f.readinto(buf)
283 except ValueError:
284 self.fail("readinto() after next() with supposedly empty "
285 "iteration-buffer failed anyway")
286 line = buf.tostring()
287 if line != testline:
288 self.fail("readinto() after next() with empty buffer "
289 "failed. Got %r, expected %r" % (line, testline))
290
291 testline = testlines.pop(0)
292 try:
293 line = f.read(len(testline))
294 except ValueError:
295 self.fail("read() after next() with supposedly empty "
296 "iteration-buffer failed anyway")
297 if line != testline:
298 self.fail("read() after next() with empty buffer "
299 "failed. Got %r, expected %r" % (line, testline))
300 try:
301 lines = f.readlines()
302 except ValueError:
303 self.fail("readlines() after next() with supposedly empty "
304 "iteration-buffer failed anyway")
305 if lines != testlines:
306 self.fail("readlines() after next() with empty buffer "
307 "failed. Got %r, expected %r" % (line, testline))
308 # Reading after iteration hit EOF shouldn't hurt either
309 f = open(TESTFN)
310 try:
311 for line in f:
312 pass
313 try:
314 f.readline()
315 f.readinto(buf)
316 f.read()
317 f.readlines()
318 except ValueError:
319 self.fail("read* failed after next() consumed file")
320 finally:
321 f.close()
322 finally:
323 os.unlink(TESTFN)
324
325
326def test_main():
327 # Historically, these tests have been sloppy about removing TESTFN.