blob: 65be30f0b2edb50cddb08fbe1b64874ea4f9990b [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 Peterson4fa88fa2009-03-04 00:14:51 +00007import io
8import _pyio as pyio
9
Serhiy Storchaka597d15a2016-04-24 13:45:58 +030010from test.support import TESTFN
Raymond Hettinger53dbe392008-02-12 20:03:09 +000011from collections import UserList
Marc-André Lemburgfa44d792000-08-25 22:37:31 +000012
Ezio Melotti3a03d2e2013-02-15 19:17:53 +020013class AutoFileTests:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000014 # file tests for which a test file is automatically set up
Raymond Hettingercb87bc82004-05-31 00:35:52 +000015
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000016 def setUp(self):
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000017 self.f = self.open(TESTFN, 'wb')
Tim Peters015dd822003-05-04 04:16:52 +000018
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000019 def tearDown(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000020 if self.f:
21 self.f.close()
22 os.remove(TESTFN)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000023
24 def testWeakRefs(self):
25 # verify weak references
26 p = proxy(self.f)
Guido van Rossume22905a2007-08-27 23:09:25 +000027 p.write(b'teststring')
Ezio Melottib3aedd42010-11-20 19:04:17 +000028 self.assertEqual(self.f.tell(), p.tell())
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000029 self.f.close()
30 self.f = None
31 self.assertRaises(ReferenceError, getattr, p, 'tell')
32
33 def testAttributes(self):
34 # verify expected attributes exist
35 f = self.f
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000036 f.name # merely shouldn't blow up
37 f.mode # ditto
38 f.closed # ditto
39
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000040 def testReadinto(self):
41 # verify readinto
Guido van Rossume22905a2007-08-27 23:09:25 +000042 self.f.write(b'12')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000043 self.f.close()
Guido van Rossum7165cb12007-07-10 06:54:34 +000044 a = array('b', b'x'*10)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000045 self.f = self.open(TESTFN, 'rb')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000046 n = self.f.readinto(a)
Ezio Melottib3aedd42010-11-20 19:04:17 +000047 self.assertEqual(b'12', a.tobytes()[:n])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000048
49 def testReadinto_text(self):
50 # verify readinto refuses text files
Guido van Rossum7165cb12007-07-10 06:54:34 +000051 a = array('b', b'x'*10)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000052 self.f.close()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000053 self.f = self.open(TESTFN, 'r')
Guido van Rossum7165cb12007-07-10 06:54:34 +000054 if hasattr(self.f, "readinto"):
55 self.assertRaises(TypeError, self.f.readinto, a)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000056
57 def testWritelinesUserList(self):
58 # verify writelines with instance sequence
Guido van Rossum7165cb12007-07-10 06:54:34 +000059 l = UserList([b'1', b'2'])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000060 self.f.writelines(l)
61 self.f.close()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000062 self.f = self.open(TESTFN, 'rb')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000063 buf = self.f.read()
Ezio Melottib3aedd42010-11-20 19:04:17 +000064 self.assertEqual(buf, b'12')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000065
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
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000083 def testErrors(self):
84 f = self.f
Ezio Melottib3aedd42010-11-20 19:04:17 +000085 self.assertEqual(f.name, TESTFN)
Serhiy Storchaka0dcd80a2015-08-02 15:17:49 +030086 self.assertFalse(f.isatty())
87 self.assertFalse(f.closed)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000088
Guido van Rossum7165cb12007-07-10 06:54:34 +000089 if hasattr(f, "readinto"):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +020090 self.assertRaises((OSError, TypeError), f.readinto, "")
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000091 f.close()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000092 self.assertTrue(f.closed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000093
94 def testMethods(self):
Guido van Rossum4b5386f2007-07-10 09:12:49 +000095 methods = [('fileno', ()),
96 ('flush', ()),
97 ('isatty', ()),
98 ('__next__', ()),
99 ('read', ()),
100 ('write', (b"",)),
101 ('readline', ()),
102 ('readlines', ()),
103 ('seek', (0,)),
104 ('tell', ()),
105 ('write', (b"",)),
106 ('writelines', ([],)),
107 ('__iter__', ()),
108 ]
Antoine Pitrou6103ab12009-10-24 20:11:21 +0000109 methods.append(('truncate', ()))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000110
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000111 # __exit__ should close the file
112 self.f.__exit__(None, None, None)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000113 self.assertTrue(self.f.closed)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000114
Guido van Rossum4b5386f2007-07-10 09:12:49 +0000115 for methodname, args in methods:
116 method = getattr(self.f, methodname)
117 # should raise on closed file
118 self.assertRaises(ValueError, method, *args)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000119
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000120 # file is closed, __exit__ shouldn't do anything
Ezio Melottib3aedd42010-11-20 19:04:17 +0000121 self.assertEqual(self.f.__exit__(None, None, None), None)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000122 # it must also return None if an exception was given
123 try:
124 1/0
125 except:
Ezio Melottib3aedd42010-11-20 19:04:17 +0000126 self.assertEqual(self.f.__exit__(*sys.exc_info()), None)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000127
Skip Montanaro80072cb2008-12-23 03:51:14 +0000128 def testReadWhenWriting(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200129 self.assertRaises(OSError, self.f.read)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000130
Ezio Melotti3a03d2e2013-02-15 19:17:53 +0200131class CAutoFileTests(AutoFileTests, unittest.TestCase):
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000132 open = io.open
133
Ezio Melotti3a03d2e2013-02-15 19:17:53 +0200134class PyAutoFileTests(AutoFileTests, unittest.TestCase):
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000135 open = staticmethod(pyio.open)
136
137
Ezio Melotti3a03d2e2013-02-15 19:17:53 +0200138class OtherFileTests:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000139
140 def testModeStrings(self):
141 # check invalid mode strings
Robert Collinsc94a1dc2015-07-26 06:43:13 +1200142 for mode in ("", "aU", "wU+", "U+", "+U", "rU+"):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000143 try:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000144 f = self.open(TESTFN, mode)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000145 except ValueError:
146 pass
147 else:
148 f.close()
149 self.fail('%r is an invalid file mode' % mode)
150
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000151 def testBadModeArgument(self):
152 # verify that we get a sensible error message for bad mode argument
153 bad_mode = "qwerty"
Tim Peterscffcfed2006-02-14 17:41:18 +0000154 try:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000155 f = self.open(TESTFN, bad_mode)
Guido van Rossumb940e112007-01-10 16:19:56 +0000156 except ValueError as msg:
Brett Cannonca477b22007-03-21 22:26:20 +0000157 if msg.args[0] != 0:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000158 s = str(msg)
Ezio Melotti7fb4da72010-03-18 12:29:13 +0000159 if TESTFN in s or bad_mode not in s:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000160 self.fail("bad error message for invalid mode: %s" % s)
Georg Brandl50da60c2008-01-06 21:38:54 +0000161 # if msg.args[0] == 0, we're probably on Windows where there may be
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000162 # no obvious way to discover why open() failed.
163 else:
164 f.close()
165 self.fail("no error for invalid mode: %s" % bad_mode)
166
167 def testSetBufferSize(self):
168 # make sure that explicitly setting the buffer size doesn't cause
169 # misbehaviour especially with repeated close() calls
170 for s in (-1, 0, 1, 512):
171 try:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000172 f = self.open(TESTFN, 'wb', s)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000173 f.write(str(s).encode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000174 f.close()
175 f.close()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000176 f = self.open(TESTFN, 'rb', s)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000177 d = int(f.read().decode("ascii"))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000178 f.close()
179 f.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200180 except OSError as msg:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000181 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000182 self.assertEqual(d, s)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000183
184 def testTruncateOnWindows(self):
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000185 # SF bug <http://www.python.org/sf/801631>
186 # "file.truncate fault on windows"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000187
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000188 os.unlink(TESTFN)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000189 f = self.open(TESTFN, 'wb')
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000190
191 try:
Guido van Rossum7165cb12007-07-10 06:54:34 +0000192 f.write(b'12345678901') # 11 bytes
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000193 f.close()
194
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000195 f = self.open(TESTFN,'rb+')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000196 data = f.read(5)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000197 if data != b'12345':
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000198 self.fail("Read on file opened for update failed %r" % data)
199 if f.tell() != 5:
200 self.fail("File pos after read wrong %d" % f.tell())
201
202 f.truncate()
203 if f.tell() != 5:
204 self.fail("File pos after ftruncate wrong %d" % f.tell())
205
206 f.close()
207 size = os.path.getsize(TESTFN)
208 if size != 5:
209 self.fail("File size after ftruncate wrong %d" % size)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000210 finally:
Guido van Rossum79b79ee2007-10-25 23:21:03 +0000211 f.close()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000212 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
Guido van Rossume22905a2007-08-27 23:09:25 +0000218 filler = b"ham\n"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000219 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
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000235 bag = self.open(TESTFN, "wb")
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000236 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:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000241 f = self.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).
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000255 f = self.open(TESTFN, 'rb')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000256 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")
Antoine Pitrou1ce3eb52010-09-01 20:29:34 +0000274 line = buf.tobytes()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000275 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))
Antoine Pitroua6e95022010-10-30 14:22:43 +0000296 f.close()
297
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000298 # Reading after iteration hit EOF shouldn't hurt either
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000299 f = self.open(TESTFN, 'rb')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000300 try:
301 for line in f:
302 pass
303 try:
304 f.readline()
305 f.readinto(buf)
306 f.read()
307 f.readlines()
308 except ValueError:
309 self.fail("read* failed after next() consumed file")
310 finally:
311 f.close()
312 finally:
313 os.unlink(TESTFN)
314
Ezio Melotti3a03d2e2013-02-15 19:17:53 +0200315class COtherFileTests(OtherFileTests, unittest.TestCase):
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000316 open = io.open
317
Ezio Melotti3a03d2e2013-02-15 19:17:53 +0200318class PyOtherFileTests(OtherFileTests, unittest.TestCase):
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000319 open = staticmethod(pyio.open)
320
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000321
Ezio Melotti3a03d2e2013-02-15 19:17:53 +0200322def tearDownModule():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000323 # Historically, these tests have been sloppy about removing TESTFN.
324 # So get rid of it no matter what.
Ezio Melotti3a03d2e2013-02-15 19:17:53 +0200325 if os.path.exists(TESTFN):
326 os.unlink(TESTFN)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000327
328if __name__ == '__main__':
Ezio Melotti3a03d2e2013-02-15 19:17:53 +0200329 unittest.main()