blob: adede2b9da82989c376da6a4fea17bd7db877a10 [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):
Georg Brandla18af4e2007-04-21 15:47:16 +000092 methods = ['fileno', 'flush', 'isatty', '__next__', 'read', 'readinto',
Thomas Wouters0e3f5912006-08-11 14:57:12 +000093 'readline', 'readlines', 'seek', 'tell', 'truncate',
94 'write', '__iter__']
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000095 if sys.platform.startswith('atheos'):
96 methods.remove('truncate')
97
Thomas Wouters0e3f5912006-08-11 14:57:12 +000098 # __exit__ should close the file
99 self.f.__exit__(None, None, None)
100 self.assert_(self.f.closed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000101
Guido van Rossum7165cb12007-07-10 06:54:34 +0000102## for methodname in methods:
103## method = getattr(self.f, methodname)
104## # should raise on closed file
105## self.assertRaises(ValueError, method)
106## self.assertRaises(ValueError, self.f.writelines, [])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000107
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000108 # file is closed, __exit__ shouldn't do anything
109 self.assertEquals(self.f.__exit__(None, None, None), None)
110 # it must also return None if an exception was given
111 try:
112 1/0
113 except:
114 self.assertEquals(self.f.__exit__(*sys.exc_info()), None)
115
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000116
117class OtherFileTests(unittest.TestCase):
118
119 def testModeStrings(self):
120 # check invalid mode strings
121 for mode in ("", "aU", "wU+"):
122 try:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000123 f = open(TESTFN, mode)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000124 except ValueError:
125 pass
126 else:
127 f.close()
128 self.fail('%r is an invalid file mode' % mode)
129
130 def testStdin(self):
131 # This causes the interpreter to exit on OSF1 v5.1.
132 if sys.platform != 'osf1V5':
Guido van Rossum7165cb12007-07-10 06:54:34 +0000133 self.assertRaises(ValueError, sys.stdin.seek, -1)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000134 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000135 print((
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000136 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000137 ' Test manually.'), file=sys.__stdout__)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000138 self.assertRaises(ValueError, sys.stdin.truncate)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000139
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000140 def testBadModeArgument(self):
141 # verify that we get a sensible error message for bad mode argument
142 bad_mode = "qwerty"
Tim Peterscffcfed2006-02-14 17:41:18 +0000143 try:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000144 f = open(TESTFN, bad_mode)
Guido van Rossumb940e112007-01-10 16:19:56 +0000145 except ValueError as msg:
Brett Cannonca477b22007-03-21 22:26:20 +0000146 if msg.args[0] != 0:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000147 s = str(msg)
148 if s.find(TESTFN) != -1 or s.find(bad_mode) == -1:
149 self.fail("bad error message for invalid mode: %s" % s)
150 # if msg[0] == 0, we're probably on Windows where there may be
151 # no obvious way to discover why open() failed.
152 else:
153 f.close()
154 self.fail("no error for invalid mode: %s" % bad_mode)
155
156 def testSetBufferSize(self):
157 # make sure that explicitly setting the buffer size doesn't cause
158 # misbehaviour especially with repeated close() calls
159 for s in (-1, 0, 1, 512):
160 try:
Guido van Rossum7165cb12007-07-10 06:54:34 +0000161 f = open(TESTFN, 'wb', s)
162 f.write(str(s).encode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000163 f.close()
164 f.close()
Guido van Rossum7165cb12007-07-10 06:54:34 +0000165 f = open(TESTFN, 'rb', s)
166 d = int(f.read().decode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000167 f.close()
168 f.close()
Guido van Rossumb940e112007-01-10 16:19:56 +0000169 except IOError as msg:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000170 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
171 self.assertEquals(d, s)
172
173 def testTruncateOnWindows(self):
174 os.unlink(TESTFN)
175
176 def bug801631():
177 # SF bug <http://www.python.org/sf/801631>
178 # "file.truncate fault on windows"
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000179 f = open(TESTFN, 'wb')
Guido van Rossum7165cb12007-07-10 06:54:34 +0000180 f.write(b'12345678901') # 11 bytes
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000181 f.close()
182
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000183 f = open(TESTFN,'rb+')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000184 data = f.read(5)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000185 if data != b'12345':
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000186 self.fail("Read on file opened for update failed %r" % data)
187 if f.tell() != 5:
188 self.fail("File pos after read wrong %d" % f.tell())
189
190 f.truncate()
191 if f.tell() != 5:
192 self.fail("File pos after ftruncate wrong %d" % f.tell())
193
194 f.close()
195 size = os.path.getsize(TESTFN)
196 if size != 5:
197 self.fail("File size after ftruncate wrong %d" % size)
198
199 try:
200 bug801631()
201 finally:
202 os.unlink(TESTFN)
203
204 def testIteration(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000205 # Test the complex interaction when mixing file-iteration and the
Guido van Rossum7165cb12007-07-10 06:54:34 +0000206 # various read* methods.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000207 dataoffset = 16384
208 filler = "ham\n"
209 assert not dataoffset % len(filler), \
210 "dataoffset must be multiple of len(filler)"
211 nchunks = dataoffset // len(filler)
212 testlines = [
Guido van Rossum7165cb12007-07-10 06:54:34 +0000213 b"spam, spam and eggs\n",
214 b"eggs, spam, ham and spam\n",
215 b"saussages, spam, spam and eggs\n",
216 b"spam, ham, spam and eggs\n",
217 b"spam, spam, spam, spam, spam, ham, spam\n",
218 b"wonderful spaaaaaam.\n"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000219 ]
220 methods = [("readline", ()), ("read", ()), ("readlines", ()),
Guido van Rossum7165cb12007-07-10 06:54:34 +0000221 ("readinto", (array("b", b" "*100),))]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000222
223 try:
224 # Prepare the testfile
225 bag = open(TESTFN, "wb")
226 bag.write(filler * nchunks)
227 bag.writelines(testlines)
228 bag.close()
229 # Test for appropriate errors mixing read* and iteration
230 for methodname, args in methods:
231 f = open(TESTFN, 'rb')
Georg Brandla18af4e2007-04-21 15:47:16 +0000232 if next(f) != filler:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000233 self.fail, "Broken testfile"
234 meth = getattr(f, methodname)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000235 meth(*args) # This simply shouldn't fail
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000236 f.close()
237
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000238 # Test to see if harmless (by accident) mixing of read* and
239 # iteration still works. This depends on the size of the internal
240 # iteration buffer (currently 8192,) but we can test it in a
241 # flexible manner. Each line in the bag o' ham is 4 bytes
242 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
243 # exactly on the buffer boundary for any power-of-2 buffersize
244 # between 4 and 16384 (inclusive).
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000245 f = open(TESTFN, 'rb')
246 for i in range(nchunks):
Georg Brandla18af4e2007-04-21 15:47:16 +0000247 next(f)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000248 testline = testlines.pop(0)
249 try:
250 line = f.readline()
251 except ValueError:
252 self.fail("readline() after next() with supposedly empty "
253 "iteration-buffer failed anyway")
254 if line != testline:
255 self.fail("readline() after next() with empty buffer "
256 "failed. Got %r, expected %r" % (line, testline))
257 testline = testlines.pop(0)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000258 buf = array("b", b"\x00" * len(testline))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000259 try:
260 f.readinto(buf)
261 except ValueError:
262 self.fail("readinto() after next() with supposedly empty "
263 "iteration-buffer failed anyway")
264 line = buf.tostring()
265 if line != testline:
266 self.fail("readinto() after next() with empty buffer "
267 "failed. Got %r, expected %r" % (line, testline))
268
269 testline = testlines.pop(0)
270 try:
271 line = f.read(len(testline))
272 except ValueError:
273 self.fail("read() after next() with supposedly empty "
274 "iteration-buffer failed anyway")
275 if line != testline:
276 self.fail("read() after next() with empty buffer "
277 "failed. Got %r, expected %r" % (line, testline))
278 try:
279 lines = f.readlines()
280 except ValueError:
281 self.fail("readlines() after next() with supposedly empty "
282 "iteration-buffer failed anyway")
283 if lines != testlines:
284 self.fail("readlines() after next() with empty buffer "
285 "failed. Got %r, expected %r" % (line, testline))
286 # Reading after iteration hit EOF shouldn't hurt either
287 f = open(TESTFN, 'rb')
288 try:
289 for line in f:
290 pass
291 try:
292 f.readline()
293 f.readinto(buf)
294 f.read()
295 f.readlines()
296 except ValueError:
297 self.fail("read* failed after next() consumed file")
298 finally:
299 f.close()
300 finally:
301 os.unlink(TESTFN)
302
303
304def test_main():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000305 # Historically, these tests have been sloppy about removing TESTFN.
306 # So get rid of it no matter what.
307 try:
308 run_unittest(AutoFileTests, OtherFileTests)
309 finally:
310 if os.path.exists(TESTFN):
311 os.unlink(TESTFN)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000312
313if __name__ == '__main__':
314 test_main()